Wednesday 13 May 2015

Exceptions in Lambdas: An Elegant Solution to a Bit of a Mess

Consider the following function for writing to a file:

The idea behind the method is to allow the user to pass in different implementations of InputStream to the method so that writeToFile can be called for example with a GZIPOuputStream, SnappyOuputStream (fast compression) or simply a plain FileInputStream.

It's a neat function which can be called like this:

Unfortunately as pointed out in the comment this does not compile!  The reason it doesn't compile is because the GZIPOutputStream throws an IOException in its constructor. What would have been nice was if the IOException was thrown out of the lambda and could then be dealt with in the try catch block - but that's not how lambdas work :-(

This is in fact how you have to deal with the exception to get the code to compile:

Not only is this ugly but you are left with the rather awkward problem of what to do with the IOException. In this case we have just re-packaged inside an AssertionError. See my previous post 'Cheating with Exceptions' on the correct way to handle this scenario. 

But there is a solution to this problem. Rather than using a java.util.function.Function that takes a value and returns a value, we can create a custom function that takes a value returns a value and throws an Exception. In this way the client code of writeToFile is nice and clean and can deal with the exception in a natural way. Moreover, lambdas are now used in the way they were intended to make our code prettier and easier to understand.

See full code listing below: