Java 8 Lambda expressions and exceptions

Java 8 Lambda expressions and exceptions

Java 8 has introduced a lot of new features, many of them well known by other languages, like lambdas expressions. Lambdas are really useful when you are encapsulating a single unit of behavior that you want to pass to other code. For example, you would use a lambda expression if you want a certain action performed on each element of a collection, when a process is completed, or when a process encounters an error. So… whats the problem with Java 8 lambda expressions and exceptions?

By default, Java 8 provides some predefined functional interfaces that can be implemented and used as a lambda expression. You can find these implementations within the package “java.util.function”. Some examples of these functional interfaces are: Consumer, Predicate, Supplier and so on. For more information about them, check this page.
One point that is important to notice when observing these predefined interfaces is that none of them define a method that throws exceptions. As a side effect it’s easy to say that you are not able to implement any lambda code that can fire checked or unchecked exceptions. Well at least not without use a try-catch block inside the lambda. The problem is that generally the lambda is not the proper guy to manipulate that exception.

Let me present you a simple code that illustrates the scenario described above.

We were forced to use a try-catch block once the accept method from the Consumer interface doesn’t throw any exception, as we can see in the following code snippet:

The good news is that we can create our own functional interface that will allow the lambdas to throw exceptions. In this example I’m going to make a new interface named UncheckedThrowingConsumer. This interface be similar to the Consumer interface, containing the accept method, but appending the “throws RuntimeException” to the method signature.

The final code would be something like this:

Then, we will need to change the MyFileWriter class to make use of the new IOExceptionThrowingConsumer interface.

And the last required modification will be made in the LambdasAndExceptions class. We can remove the try-catch block and let the exception flow its course.

In this article we could see how flexible and powerful the functional interfaces are when combined to lambda expressions. It’s always important to remember that be able to do something doesn’t necessarily means that it’s a good approach or the best design for a specific problem. Hopes this explanation could help you with some similar problem.