【问题标题】:Java 8 requireNonNull method with supplier parameter performance具有供应商参数性能的 Java 8 requireNonNull 方法
【发布时间】:2019-01-16 11:18:56
【问题描述】:

在 Java 8 中添加了 Objects.requireNonNullSupplier 方法,但我不确定声明的性能改进是什么:

虽然这可能会带来在非空情况下的性能优势,但在决定调用此方法时应注意创建消息提供者的成本低于成本直接创建字符串消息。

String 方法如果不为空则忽略参数:

public static <T> T requireNonNull(T obj, String message) {
    if (obj == null)
        throw new NullPointerException(message);
    return obj;
}

我找到JDK-8011800 : Add java.util.Objects.requireNonNull(T, Supplier)

在 JDK 7 中,java.util.Objects 包含多种检查 null 的方法,其中包括一个在找到 null 时返回消息的方法。对于 JDK 8 中的 lambda,另一个要包含的变体是 requireNonNull 方法,它采用字符串供应商而不是字符串。这就是为什么在非空情况下可以避免创建字符串消息的成本。请注意,lambda 捕获的成本可能不为零。

带注释表示对性能没有影响:

非零捕获成本确实让我担心。 我担心它会经常抹杀使用供应商的任何优势。 09-04-2013

我发现了其他问题,但不是指(为什么)发送字符串参数有性能成本

它是否特定于 lambda 表达式/流的使用?

【问题讨论】:

  • probably 意味着创建字符串并非微不足道(与性能相关)的情况,例如必须调用 expensive 方法 - 基于最后一个“...消息供应商的成本低于直接创建字符串消息的成本”的一部分
  • 想一个复杂的错误信息,包括程序状态信息
  • StringBuilder(或+ 连接)、String.format 以及我在评论中添加的内容,调用了一些其他方法(“此方法允许将消息的创建推迟到进行空检查后") - 如果被测对象不为空,则无需创建消息,但如果方法以字符串形式获取消息,则它已经完成
  • 正是文档中提示相同的部分:与方法requireNonNull(Object, String)不同,此方法允许消息的创建被推迟到进行空检查之后
  • 如果涉及字符串连接或使用格式化程序的示例不能说服您,请考虑从资源包中加载消息。

标签: java string object java-8 null-check


【解决方案1】:

考虑一下,generateString 做了很多事情来从someParam 生成字符串:

Objects.requireNonNull(obj, generateString(someParam));

在 Java 中参数是热切求值的,这意味着 generateString 将在调用 requireNonNull 之前求值。因此,无论obj 是否为空,都会计算它。

您可以通过将其更改为以下内容来解决此问题:

Objects.requireNonNull(obj, () -> generateString(someParam));

在这种情况下,generateString 只会在obj 实际为空时被调用。当generateString 比创建Supplier 对象更昂贵时,这会更有效。

如果你的 String 参数只是一个文字,你应该只使用普通的非 lambda 方法,比如:

Objects.requireNonNull(obj, "obj was null!");

【讨论】:

  • 有没有办法在创建字符串的费用和创建供应商的费用之间取得平衡?
猜你喜欢
  • 2014-05-19
  • 2015-09-23
  • 1970-01-01
  • 2012-11-25
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多