Vartlok Vartlok - 2 months ago 28
Java Question

Java 8 method reference unhandled exception

I'm working on project with Java 8 and found one situation which I can't understand.

I have code like this:

void deleteEntity(Node node) throws SomeException {
for (ChildNode child: node.getChildren()) {
deleteChild(child);
}
}

void deleteChild(Object child) throws SomeException {
//some code
}


This code is working fine, but I can rewrite it with a method reference:

void deleteEntity(Node node) throws SomeException {
node.getChildren().forEach(this::deleteChild);
}


And this code doesn't compile, giving the error
Incompatible thrown types *SomeException* in method reference
.

Also IDEA gave me the error
unhandled exception
.

So, my question is why? Why code compiles with for each loop and doesn't compile with lambda?

Answer

If you look at the Consumer<T> interface, the accept method (which is what your method reference would effectively be using) isn't declared to throw any checked exceptions - therefore you can't use a method reference which is declared to throw a checked exception. The enhanced for loop is okay, because there you're always in a context where SomeException can be thrown.

You could potentially create a wrapper which converts the checked exception to an unchecked exception, and throw that. Alternatively, you could declare your own functional interface with an accept() method which does throw a checked exception (probably parameterizing the interface with that exception), and then write your own forEach method that takes that functional interface as an input.