Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

November Discount Launch 2022 – TEMP TOP (NPI)
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

1. Overview

In Java, the sneaky throw concept allows us to throw any checked exception without defining it explicitly in the method signature. This allows the omission of the throws declaration, effectively imitating the characteristics of a runtime exception.

In this article, we'll see how this is done in practice, by looking at some code examples.

2. About Sneaky Throws

Checked exceptions are part of Java, not the JVM. In the bytecode, we can throw any exception from anywhere, without restrictions.

Java 8 brought a new type inference rule that states that a throws T is inferred as RuntimeException whenever allowed. This gives the ability to implement sneaky throws without the helper method.

A problem with sneaky throws is that you probably want to catch the exceptions eventually, but the Java compiler doesn't allow you to catch sneakily thrown checked exceptions using exception handler for their particular exception type.

3. Sneaky Throws in Action

As we already mentioned, the compiler and the Jave Runtime can see different things:

public static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
    throw (E) e;
}

private static void throwSneakyIOException() {
    sneakyThrow(new IOException("sneaky"));
}

The compiler sees the signature with the throws T inferred to a RuntimeException type, so it allows the unchecked exception to propagate. The Java Runtime doesn't see any type in the throws as all throws are the same a simple throw e.

This quick test demonstrates the scenario:

@Test
public void throwSneakyIOException_IOExceptionShouldBeThrown() {
    assertThatThrownBy(() -> throwSneakyIOException())
      .isInstanceOf(IOException.class)
      .hasMessage("sneaky")
      .hasStackTraceContaining("SneakyThrowsExamples.throwSneakyIOException");
}

Furthermore, it's possible to throw a checked exception using bytecode manipulation, or Thread.stop(Throwable), but it's messy and not recommended.

4. Using Lombok Annotations

The @SneakyThrows annotation from Lombok allows you to throw checked exceptions without using the throws declaration. This comes in handy when you need to raise an exception from a method within very restrictive interfaces like Runnable.

Say we throw an exception from within a Runnable; it will only be passed to the Thread's unhandled exception handler.

This code will throw the Exception instance, so there is no need for you to wrap it in a RuntimeException:

@SneakyThrows
public static void throwSneakyIOExceptionUsingLombok() {
    throw new IOException("lombok sneaky");
}

A drawback with this code is that you cannot catch a checked exception that is not declared. For instance, if we try to catch the IOException sneakily thrown by the method above, we would get a compilation error.

Now, let's call throwSneakyIOExceptionUsingLombok and expect Lombok to throw the IOException:

@Test
public void throwSneakyIOExceptionUsingLombok_IOExceptionShouldBeThrown() {
    assertThatThrownBy(() -> throwSneakyIOExceptionUsingLombok())
      .isInstanceOf(IOException.class)
      .hasMessage("lombok sneaky")
      .hasStackTraceContaining("SneakyThrowsExamples.throwSneakyIOExceptionUsingLombok");
}

5. Conclusion

As we have seen in this article, we can trick the Java compiler to treat checked exceptions as unchecked.

As always, the code is available over on GitHub.

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

Generic footer banner
4 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Comments are closed on this article!