Application of @Sneaky Throws in lombok

Viewed 15023

I was playing with the Lombok library in Java and found an annotation called @SneakyThrows. As the documentation states:

@SneakyThrows fakes out the compiler. In other words, Lombok doesn't wrap or replace the thrown checked exception, but makes the compiler think that it is an unchecked exception.

With other words, this is a way to bypass exceptions at compile time. But in my opinion this should not be the correct way of handling exceptions, because the bypassed exception can show weird behaviour at runtime.

So in which scenario should @SneakyThrows be used?

3 Answers

To add to the existing answers. I personally dislike checked exceptions. See for more info: https://phauer.com/2015/checked-exceptions-are-evil/

To add insult to injury, the code gets bloated when avoiding the checked exceptions. Consider the usage of @SneakyThrows:

 List<Instant> instantsSneaky = List.of("2020-09-28T12:30:08.797481Z")
        .stream()
        .map(Example::parseSneaky)
        .collect(Collectors.toList());

@SneakyThrows
private static Instant parseSneaky(String queryValue) {
    return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(queryValue).toInstant();
}

versus non-@SneakyThrows

 private static Instant parseNonSneaky(String queryValue) throws ParseException {
    return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(queryValue).toInstant();
}

List<Instant> instantsNonSneaky = List.of("2020-09-28T12:30:08.797481Z")
        .stream()
        .map(timeStamp -> {
            try {
                return parseNonSneaky(timeStamp);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        })
        .collect(Collectors.toList());

Hence the applicance of @SneakyThrows enables much cleaner code.

I believe the intention here is to cause the compiler to not require a throws whatever Exception to be added to the method declaration.

For example if the method was

public void throwsCheckedException() {
    throw new IOException("IO exception thrown");
}

This would cause a compile time exception requiring

public void throwsCheckedException() throws IOException {
    throw new IOException("IO exception thrown");
}

The annotation @SneakThrows mitigates this - original method declared as

@SneakyThrows
public void throwsCheckedException() {
    throw new IOException("IO exception thrown");
}

This will not cause a compile time error. Note IDEs might still highlight this as an error, for example in IntelliJ you will need to utilise the Lombok plugin.

In the JAVA 8 and above when using lambda especially its not an easy way to use.

  1. Consider it mostly for older versions of Java 8.
  2. The purpose itself is to throw an exception deliberately for example for warning. By this the other services/program/code can identify how the request/response flow should be handled. If you already have mechanism in place no need to worry about it.

@SneakyThrows is not of much use in current traditional application development, could be used in some kinda state machine programs where it would be necessary (i do not have expertise in it though) to determine the state of the programs current flow. This is just 1 example of different scenarios there maybe more.

Related