A little backstory (ok, a lot): I've been working on creating classes that take java.util.function
types and wrap their execution with try/catch
blocks to remove the need for using try/catch
from within lambda statements. Something that would allow this test code:
list.forEach(ExceptionWrapper.wrapConsumer(s -> {throw new Exception(s);}));
In doing so, I came up with this. It did not work.
public class ExceptionWrapper {
public static <T> Consumer<T> wrapConsumer(Consumer<T> consumer){
return t -> {
try {
consumer.accept(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
}
Many incantations always result in
Error:(54, 61) java: unreported exception java.lang.Exception; must be caught or declared to be thrown
After much searching, I came across the jOOλ code. It looked nearly the same except they use an intermediary lambda construct that mimics the wrapped types but declares to throw an exception. I made my own (did NOT copy the code, just the concept) and it works pretty awesome
public interface ConsumerWrapper<T>{
void accept(T t) throws Exception;
}
and making the change in ExceptionWrapper
public static <T> Consumer<T> wrapConsumer(ConsumerWrapper<T> consumer){
... // ^ note change
}
allows the initial test code to compile and run.
public static void main(String[] args) {
List<String> strings = Arrays.asList("1");
strings.forEach(System.out::println);
strings.forEach(ExceptionWrapper.wrapConsumer(s -> {throw new Exception(s);}));
}
Exception in thread "main" java.lang.RuntimeException: java.lang.Exception: 1 at crap.unk.ExceptionWrapper.lambda$wrapConsumer$2(ExceptionWrapper.java:39) at crap.unk.ExceptionWrapper$$Lambda$3/1401420256.accept(Unknown Source) ... Caused by: java.lang.Exception: 1 at crap.unk.ExceptionWrapper.lambda$main$3(ExceptionWrapper.java:54) at crap.unk.ExceptionWrapper$$Lambda$2/501263526.accept(Unknown Source)
THE QUESTION
Why wouldn't my original attempt work? Why does the use of the intermediary, that has the identical structure, make it work? It seems caused by the difference in thethrows
clause but I don't see why. Why is it different than passing an Object
off to a method and surrounding a call with a try/catch
?