Use jOOλ’s Sneaky Throw to Avoid Checked Exceptions

Don’t you hate how you have to wrap checked exception throwing code in static initialisers? E.g. you cannot write this in Java:

public class Test {
    static final Class<?> klass = Class.forName("org.h2.Driver");
}

There’s an unhandled ClassNotFoundException, and you can’t catch / rethrow it simply. A static initialiser is needed:

public class Test {
    static final Class<?> klass;

    static {
        try {
            klass = Class.forName("org.h2.Driver");
        }
        catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

Yuck.

Luckily, one of jOOλ’s lesser known features is the Sneaky class, which contains a bunch of utility methods that wrap a JDK functional interface to an equivalent, “sneaky-throwing” functional interface that doesn’t declare the checked exception.

In short, you can write:

public class Test {
    static final Class<?> klass = Sneaky.supplier(
        () -> Class.forName("org.h2.Driver")
    ).get();
}

The exception is simply re-thrown “sneakily”, as the JVM doesn’t care about an exception’s checked-ness. If you don’t have H2 on your classpath, you’ll get:

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.ClassNotFoundException: org.h2.Driver
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:375)
	at org.jooq.test.util.Test.lambda$0(Test.java:44)
	at org.jooq.lambda.Unchecked.lambda$supplier$38(Unchecked.java:1695)
	at org.jooq.test.util.Test.<clinit>(Test.java:44)

You can use this approach wherever else a JDK functional interface is required, and you don’t care about an exception’s checked-ness, e.g. in streams:

// Doesn't compile:
Stream
    .generate(
        () -> Class.forName("org.h2.Driver"))
    .limit(1)
    .forEach(System.out::println);

// So ugly
Stream
    .generate(
        () -> {
            try {
                return Class.forName("org.h2.Driver");
            }
            catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        })
    .limit(1)
    .forEach(System.out::println);

// Use jOOλ's Sneaky supplier
Stream
    .generate(Sneaky.supplier(
        () -> Class.forName("org.h2.Driver")))
    .limit(1)
    .forEach(System.out::println);

Get jOOλ here: https://github.com/jOOQ/jOOL

4 thoughts on “Use jOOλ’s Sneaky Throw to Avoid Checked Exceptions

  1. This approach breaks the guarantees that the language provides with regard to checked exceptions. The fact that the language fails to enforce them by providing ways to get around the checks, does not mean that it is a good idea to go ahead and break the guarantees. If people use sneaky throwing, then the code that reasonably catches only RuntimeException because a method does not declare throwing any checked exceptions may not work correctly because it misses the checked exceptions that are not supposed to be thrown. Using sneaky throwing is a terrible idea.

    1. Yeah, meh. Because the alternative is to wrap the checked exception in a random RuntimeException (or even RuntimeException itself), and then to catch that, or Exception, or Throwable as a last resort. I mean, let’s be honest. These things are usually done for non-recoverable exceptions, so they might as well bubble up to the top level.

      What’s the alternative, in your opinion, with respect to the Class.forName() case? Does it really matter? Is it really terrible (because if it is, you *must* have an alternative!)

Leave a Reply to Valentin Cancel reply