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/[email protected]/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.
sneakyThrow
inside ofrethrow
to throw the original, checked exception instead of wrapping it in aRuntimeException
. Alternatively you could use the@SneakyThrows
annotation from Project Lombok that does the same thing.Consumer
s inforEach
may be executed in parallel fashion when using parallelStream
s. A throwable raised from withing the consumer will then propagate to the calling thread, which 1) won't stop the other concurrently running consumers, which may or may not be appropriate, and 2) if more than one of the consumers throw something, only one of the throwables will be seen by the calling thread.