Exception Handling in Eclipse Collections
Some strategies for handling exceptions in Eclipse Collections before and after Java 8
The Inspiration for this post
Brian Vermeer wrote a great blog on Exception Handling in Java Streams.
The post reminded me of the exception handling support we have had in Eclipse Collections for a few years now. I thought I would show some simple examples of handling Checked Exceptions using Eclipse Collections before and after Java 8. I will also show examples that will work with Java Streams.
The Dependable Appendable
There is an interface in Java named Appendable
. Appendable
is a parent interface of StringBuilder
, StringBuffer
, PrintStream
and several other classes. The interface has been around since Java 5. It defines a method append
as follows:
If I create a MutableList
of String
, and attempt to use append
as a method reference with the forEach
method, my IDE gives me a warning saying there is an Unhandled Exception: java.io.IOException
.
As it turns out, StringBuilder
doesn’t actually throw a java.io.IOException
in its method signature for the append
method. So if I change the type to StringBuilder
, the exception will go away.
The same would be true if I changed the code to use StringBuffer
. However, all Appendable
implementations that deal with files will most likely throw the exception. So if I use the interface, and not specific implementations, I will have to handle the exception. The ugly way of handling the exception prior to Java 8, might look as follows.
This is a common pattern, catching a checked exception and throwing a RuntimeException
. It was common enough for us before Java 8 that we had specific “Checked” versions of the different functional interfaces in Eclipse Collections. There is a package named “checked” in each of the functional interface packages (function, predicate, procedure). Using a CheckedProcedure
, we could simplify the code as follows:
If an exception is thrown by the Appendable
, the exception will be caught and if it is a RuntimeException
, it will be bubbled up. If it is a checked exception, a RuntimeException
will be created and thrown with the checked exception set as the cause.
After Java 8, we introduced new interfaces to deal with Checked Exceptions. For each Functional Interface type (Function
, Predicate
, Procedure
) there is a corresponding “throwing” type (ThrowingFunction
, ThrowingPredicate
, ThrowingProcedure
). There are also corresponding methods on the factories for the the functional interfaces (Functions.throwing
, Predicates.throwing
, Procedures.throwing
). Using the combination of these features with Java 8 or above we can now write the following:
You can also use the same approach with Java Collections and Java Streams.
This code works, because the Procedure
interface in Eclipse Collections extends the Consumer
interface. The code will work using as a Stream
as well.
Throwing your own RuntimeExceptions
If you want to control the type of RuntimeException that is thrown, there is an overloaded version of the throwing method that supports this.
Let’s say I want to rethrow an UndependableAppendableException
in case an IOException
is caught in the call to append
. The code might look as follows:
Notice, I kept the code here working with Java Stream. It would work the same using forEach
on a List
or a MutableList
from Eclipse Collections.
But wait, what about…
This is the exception handling capability that exists today in Eclipse Collections. If there are additional capabilities you would like, consider submitting issues requesting features or making contributions via pull requests to the Eclipse Collection project. We welcome new contributors to Eclipse Collections. Check out the following blog for more information on how to get started.
I am a Project Lead and Committer for the Eclipse Collections OSS project at the Eclipse Foundation. Eclipse Collections is open for contributions. If you like the library, you can let us know by starring it on GitHub.