VOOZH about

URL: https://www.javacodegeeks.com/2015/05/exceptions-in-lambdas-an-elegant-solution-to-a-bit-of-a-mess.html

⇱ Exceptions in Lambdas: An Elegant Solution to a Bit of a Mess - Java Code Geeks


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.

private static void writeToFile(File file, String value,
 Function<OutputStream, OutputStream> writing) throws IOException{
 try (PrintWriter pw = new PrintWriter(new BufferedOutputStream
 (writing.apply(new FileOutputStream(file))))) {
 pw.write(value);
 }
}

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

public static void main(String[] args) {
 try {
 //Write with compression
 //DOES NOT COMPILE!!
 writeToFile(new File("test"), "Hello World", GZIPOutputStream::new);
 //Just use the FileOutputStream
 writeToFile(new File("test"), "Hello World", i->i);
 }catch(IOException e){
 //deal with exception as you choose
 }
}

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:

public static void main(String[] args) {
 try {
 //Write with compression
 //COMPILES BUT SO UGLY
 writeToFile(new File("test"), "Hello World", i -> {
 try {
 return new GZIPOutputStream(i);
 } catch (IOException e) {
 //HOW ARE WE SUPPOSED TO DEAL WITH THIS EXCEPTION??
 throw new AssertionError(e);
 }
 });
 //Just use the FileOutputStream
 writeToFile(new File("test"), "Hello World", i->i);
 }catch(IOException e){
 //deal with exception as you choose
 }
}

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:

package util;
 
import java.io.*;
import java.util.zip.GZIPOutputStream;
 
public class LambdaExceptions {
 public static void main(String[] args) {
 try {
 //Write with compression
 writeToFile(new File("test"), "Hello World", GZIPOutputStream::new);
 //Just use the FileOutputStream
 writeToFile(new File("test"), "Hello World", i->i);
 }catch(IOException e){
 //deal with exception as you choose
 }
 }
 
 private static void writeToFile(File file, String value, 
 ThrowingFunction<OutputStream, OutputStream, IOException> writing) throws IOException{
 try (PrintWriter pw = new PrintWriter(new BufferedOutputStream
 (writing.apply(new FileOutputStream(file))))) {
 pw.write(value);
 } 
 }
 
 @FunctionalInterface
 public interface ThrowingFunction<I, O, T extends Throwable> {
 O apply(I i) throws T;
 }
}
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Thank you!

We will contact you soon.

Tags
Lambdas
👁 Photo of Daniel Shaya
Daniel Shaya
May 15th, 2015Last Updated: May 15th, 2015
0 119 2 minutes read

Daniel Shaya

Daniel has been programming in Java since it was in beta. Working predominantly in the finance industry he has created real time trading and margin risk applications. He is currently a director at OpenHFT where we are building next generation Java low latency products.
Subscribe

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button
Close
wpDiscuz