Consider the following example:
public class LambdaArgsTest {
private static void display(Supplier<?> arg) {
try {
// this is the place where the Exception("wrong") might be thrown
// and it is in fact handled
System.out.println(arg.get());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
display(() -> {
if(/*some condition*/) {
// this statement will be rejected due to unhandled exception
throw new Exception("wrong");
}
return "abcde";
});
}
}
Here comes the question: the lambda argument in the above example is an object that'll be executed later inside the "display()" method. It is obviously not executed when passing the arguments to the "display()".
Why is it rejected by the compiler? I think it's quite reasonable to surround it by try...catch only when the lambda is actually called.
This is because of the signature of
Supplierfunctional interface:As you see, the method
getis not declared to throwException(neither any other checked exception).In Java, there are checked vs unchecked exceptions (unchecked exceptions are those which inherit from
RuntimeException). Checked exceptions must be handled, either by catching them in acatchblock, or by declaring that the methodthrowsthat exception.If the signature of
Supplier.getwere:The code would compile fine.
Try throwing
RuntimeExceptioninstead ofExceptionand the code will compile fine.EDIT: As per Peter Lawrey's suggestion in the comments, if you do need to throw a checked exception from within your lambda expression, you could use e.g.
Callable, whose only one method's signature is as follows:You'd just need to pass a
Callableto yourdisplaymethod instead of aSupplier.