I appreciate a lot the new Java 8 features about lambdas and default methods interfaces. Yet, I still get bored with checked exceptions. For instance, if I just want to list all the visible fields of an object I would like to simply write this:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
Yet, since the get
method might throw a checked exception, which does not agrees with the Consumer
interface contract, then I must catch that exception and write the following code:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
However in most cases I just want the exception to be thrown as a RuntimeException
and let the program handle, or not, the exception without compilation errors.
So, I would like to have your opinion about my controversial workaround for checked exceptions annoyance. To that end, I created an auxiliary interface ConsumerCheckException<T>
and an utility function rethrow
(updated according to the sugestion of Doval's comment) as follows:
@FunctionalInterface
public interface ConsumerCheckException<T>{
void accept(T elem) throws Exception;
}
public class Wrappers {
public static <T> Consumer<T> rethrow(ConsumerCheckException<T> c) {
return elem -> {
try {
c.accept(elem);
} catch (Exception ex) {
/**
* within sneakyThrow() we cast to the parameterized type T.
* In this case that type is RuntimeException.
* At runtime, however, the generic types have been erased, so
* that there is no T type anymore to cast to, so the cast
* disappears.
*/
Wrappers.<RuntimeException>sneakyThrow(ex);
}
};
}
/**
* Reinier Zwitserloot who, as far as I know, had the first mention of this
* technique in 2009 on the java posse mailing list.
* http://www.mail-archive.com/javaposse@googlegroups.com/msg05984.html
*/
public static <T extends Throwable> T sneakyThrow(Throwable t) {
throw (T) t;
}
}
And now I can just write:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
I am not sure that this is the best idiom to turn around the checked exceptions, but as I explained, I would like to have a more convenient way of achieving my first example without dealing with checked exceptions and this is the simpler way that I found to do it.