Can you please explain why checked exceptions have to be caught from within lambda expressions? In other words, why does the following code not compile...
public void doSomething(ObjectInputStream istream) throws IOException {
// The read method throws an IOException.
IntStream.range(0, 10).forEach(i -> someList.add(read(istream)));
}
but this one will?
public void doSomething(ObjectInputStream istream) throws IOException {
IntStream.range(0, 10).forEach(i -> {
try {
// The read method throws an IOException.
someList.add(read(istream));
}
catch (IOException ioe) {
// Callee has to handle checked exception, not caller.
}
});
}
It seems like the callee now has to handle any checked exceptions that are thrown and not the caller.
The issue isn't the lambda expression, it's the interface it's implementing. Remember, a lambda expression is basically just shorthand for an anonymous class that implements a given interface.
In this case,
forEach
takes ajava.util.function.Consumer<T>
:Note that
accept
is not declared to throw anything. This means that no implementation of it can throw anything; not a named class, not an anonymous class, and not a lambda.It seems that your
read
method throwsIOException
.The signature of
IntStream.forEach
isforEach(IntConsumer action)
, whereIntConsumer
has avoid accept(int value)
method. In that context your lambda expressioni -> someList.add(read(istream))
is equivalent to:which doesn't compile because
read
throws a checked exception.On the other hand, lambda expressions may throw checked exceptions if the functional interface defines them (which is not the case for consumers or other
java.util
functional interfaces).Suppose the following made up example:
Now the following compiles: