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
Supplier
functional interface:As you see, the method
get
is 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 acatch
block, or by declaring that the methodthrows
that exception.If the signature of
Supplier.get
were:The code would compile fine.
Try throwing
RuntimeException
instead ofException
and 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
Callable
to yourdisplay
method instead of aSupplier
.