【问题标题】:Is constructing an exception slower than constructing an exception supplier? [duplicate]构造异常是否比构造异常提供者慢? [复制]
【发布时间】:2021-11-17 12:53:49
【问题描述】:

为什么我们必须这样写?创建异常实例是否比创建供应商实例更昂贵?

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

【问题讨论】:

  • 这可能是重复的,所以我不会将其添加为答案 - 但基本上,每次执行该行代码时,您的第二段代码都会创建一个 NullPointerException 的新实例.第一段代码只在需要时构造异常
  • 是否每次都创建供应商是一个实现细节; JLS 表示允许方法引用表达式(或 lambda 表达式)重用缓存值。
  • 另一个区别是,原则上,您可以编写.orElseThrow(() -> { ...; return new SomethingException(); }),其中... 部分具有您想要在抛出某些东西的情况下执行的副作用(例如用于调试目的的日志记录) .
  • @BogdanTischenko 是否创建供应商似乎是一个实施细节,但我认为更重要的是我们可以先验地判断创建供应商的成本是最低的。可以创建一个自定义异常类并潜入构造函数中解决 NP 完全问题。因此,对于创建异常的成本没有先验限制。
  • 这本质上是 stackoverflow.com/q/33170109/2541560 的复制品,它的异常并没有改变任何东西。

标签: java exception optional


【解决方案1】:

.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();
}

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

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


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

【讨论】:

  • 构造函数中的fillInStackTrace() 就是我要找的。我认为异常的性能损失来自于抛出它们,而不是调用构造函数
  • @BogdanTischenko 我们有一个 Throwable 的特定构造函数可以让你选择退出它,但我怀疑在实践中它很少使用,你几乎可以忽略它。 NPE 和朋友都会收集堆栈跟踪。 99% 的时间你想要一个堆栈跟踪。尽管如此,为了准确起见,我还是稍微更新了答案
  • @BogdanTischenko 抛出它们也可以降低性能——这取决于抛出点和异常处理程序之间的距离,但是,收集堆栈跟踪确实是最昂贵的部分。如果您对更多细节感兴趣,可以阅读“The Exceptional Performance of Lil' Exception”。顺便说一句,NullPointerException::new 是非捕获的,这意味着一旦构造了这个Supplier,它(通常)会在应用程序的整个生命周期内被重复使用,因此即使是这个很小的构造成本也可以节省。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
  • 2012-04-14
  • 1970-01-01
相关资源
最近更新 更多