Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Application of @Sneaky Throws in lombok

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?

like image 800
Shivanshu Avatar asked Oct 05 '20 12:10

Shivanshu


People also ask

What does @sneaky throws do?

Overview. @SneakyThrows can be used to sneakily throw checked exceptions without actually declaring this in your method's throws clause. This somewhat contentious ability should be used carefully, of course.

Can we use throws at class level?

You can by throw exception at constructor level.

What does a checked exception mean?

A checked exception is a type of exception that must be either caught or declared in the method in which it is thrown. For example, the java.io.IOException is a checked exception.

Can we use throw without throws Java?

Without using throwsWhen an exception is cached in a catch block, you can re-throw it using the throw keyword (which is used to throw the exception objects). If you re-throw the exception, just like in the case of throws clause this exception now, will be generated at in the method that calls the current one.


2 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.

like image 123
SnowmanXL Avatar answered Sep 22 '22 13:09

SnowmanXL


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.

like image 45
MarkAddison Avatar answered Sep 21 '22 13:09

MarkAddison