构建异常是否比构建异常供应商慢?

Is constructing an exception slower than constructing an exception supplier?

为什么要这样写呢?创建异常实例是否比创建供应商实例更昂贵?

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

.orElseThrow(NullPointerException::new) 等同于 () -> new NullPointerException().

这是一个只有在 Optional 为空时才会调用的函数

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

优于 .orElseThrow(new NullPointerException()) 的原因是性能。当你传递一个函数时,如果你真的需要抛出它,你只是按需创建一个异常。

相对而言,创建大多数异常是昂贵的*。构造函数几乎总是会创建一个堆栈跟踪,并且构建堆栈跟踪相对较慢*。收集堆栈跟踪已完成 within Throwable's constructor.

public Throwable() {
    fillInStackTrace();
}

有一个变体构造函数不会收集堆栈跟踪,但很少使用。

他们本可以提供第二个签名以允许人们在他们之间进行选择,但您建议的签名很可能会经常被滥用,从而导致性能下降。


* 'Expensive' 和 'slow' 是相对术语。现代 CPU 。虽然它可能比大多数正常操作慢得多,但它通常不会成为大多数应用程序或类似应用程序的瓶颈。