Search code examples
javaexceptionoption-type

Is constructing an exception slower than constructing an exception supplier?


Why do we have to write it like so? Is creating an exception instance more expensive than creating a supplier instance?

var value = getOptional().orElseThrow(NullPointerException::new);
// instead of
var value = getOptional().orElseThrow(new NullPointerException());

Solution

  • .orElseThrow(NullPointerException::new) is equivalent to () -> new NullPointerException().

    That's a function which will only be invoked if the Optional is empty

    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get(); // Only invoke on this path
        }
    }
    

    Code

    The reason that's preferable to .orElseThrow(new NullPointerException()) is because of performance. When you pass a function, you are only create an exception on-demand, if you really need to throw it.

    Creating most exceptions is expensive*, relatively speaking. The constructor will almost always create a stacktrace, and constructing the stacktrace is relatively slow*. Gathering the stacktrace is done within Throwable's constructor.

    public Throwable() {
        fillInStackTrace();
    }
    

    There is a variant constructor which won't gather the stacktrace, but it's very rarely used.

    They could have provided a second signature to allow people to choose between them, but it's likely that the signature you suggested would be frequently misused, resulting in worse performance.


    * 'Expensive' and 'slow' are relative terms. Modern CPUs are fast. While it may be significantly slower than most normal operations, it's generally not going to be a bottleneck on most applications or anything like that.