在方法参考表达式评估中进行空检查的原因是什么?

Yan*_*ann 6 java nullpointerexception java-8 method-reference

有很多问题让人们意识到用一个表达式来计算一个null值来创建一个方法引用会产生一个NullPointerException.举个例子:

String s = null;
Supplier<char[]> fun = s::toCharArray;
Run Code Online (Sandbox Code Playgroud)

这是由于java规范中的以下段落:

首先,如果方法引用表达式以ExpressionName或Primary开头,则计算此子表达式.如果子表达式的计算结果为null,则会引发NullPointerException,并且方法引用表达式会突然完成.如果子表达式突然完成,则方法引用表达式会出于同样的原因突然完成.

现在我的问题是,有没有人碰巧知道背后的原因(基于许多困惑的问题)反直觉规范是什么?

我唯一想到的是,在以下情况下,很难准确地报告NullPointerException在评估期间发生的错误Supplier:

public static char[] callback(Supplier<char[]> supplier) {
    return supplier.get();
}

public static void main(String[] args) {
    String s = null;
    callback(s::toCharArray);
}
Run Code Online (Sandbox Code Playgroud)

max*_*ver 7

这里的原因是,当您创建非静态方法引用时,它必须具有访问权限this.当您尝试创建对空对象的引用时,没有this任何地方,这就是为什么它应该在此步骤失败,而不是在第一次使用时在代码中的某个地方失败.

想象一下,在一个地方你得到了对象,在某处保存它的方法引用,而不是在完全不同的代码部分中使用它.你会得到一个NPE,而不是在发生错误的地方,但是会有很多代码行.

  • @YanickSalzmann有两种相反的设计方法,即"你尝试使用它的精细"方法,你提到的"快速失败,尽快发现错误"的方法.较新语言功能和相关API的设计者显然偏爱后一种风格.当你在空集合上尝试`forEach(null)`时,你会注意到.大多数实现都会故意检查消费者的"null"和throw,即使他们不需要触摸它.请注意,方法引用的行为与旧的`expression.new InnerClass()`语言功能相同 (3认同)