Prefer Lombok’s @SneakyThrows to rethrowing checked exceptions as RuntimeExceptions

By Adrian Smith29 Mar 2018400 words2 mins to read

The traditional way of dealing with a checked exception being thrown from a place where you know it can't actually be thrown, is to re-throw it as a RuntimeException. That way in case it does actually happen, you'll know about it, and have the full stack trace available.

public void foo() {
    try {
        Writer w = .....
        w.write("foo");
        ....
    } catch (IOException e) {
       throw new RuntimeException(e); 
    }
}

Project Lombok offers the annotation @SneakyThrows which allows you to write the above code as follows:

@SneakyThrows(IOException.class)
public void foo() {
    Writer w = .....
    w.write("foo");
    ....
}

I was always conflicted about this annotation: is it better than just re-throwing the exception as a RuntimeException? I prefer to use standard features of the JDK if possible. The @SneakyThrows doesn't really offer that much benefit.

Both approaches show that you've thought about the exception, and realized that it can be safely ignored, so neither approach is superior from that perspective.

But after a lot of consideration I now recommend the usage of @SneakyThrows.

If you have a long method which doesn't need to catch any exceptions, and then a new line is introduced which requires the catching of an exception, the whole method must be surrounded by a try, and with that indented. That makes Git think that the whole method has changed. If anyone else has altered a different line in that method, that's now going to be a merge conflict. Adding the line together with @SneakyThrows means no intending, meaning your change can merge with other people's changes without conflict.

A minor advantage is that the exception stack backtrace is simpler. @SneakyThrows doesn't actually catch and re-throw the exception; the original exception is not caught and it simply propagates as if it were a RuntimeException. So the backtrace is not interrupted by a "Caused By:" line.

The code is also slightly shorter as well, and concise code - expressing the same logic with less irrelevant waffle for your readers to wade through - is always something to be desired, in my opinion.

This article was written by Adrian Smith on 29 Mar 2018

Follow me: Facebook | Twitter | LinkedIn | Email

More on: Java | Coding