ste*_*fen 7 java lambda jvm ternary-operator
我在当前版本的Java 8中发现了一个奇怪的行为.在我看来,下面的代码应该没问题,但JVM会抛出NullPointerException:
Supplier<Object> s = () -> false ? false : false ? false : null;
s.get(); // expected: null, actual: NullPointerException
Run Code Online (Sandbox Code Playgroud)
没关系,它是什么样的lambda表达式(与之相同java.util.function.Function)或使用什么泛型类型.也可以用更有意义的表达来代替false ? :.上面的例子非常简短.这是一个更加丰富多彩的例子:
Function<String, Boolean> f = s -> s.equals("0") ? false : s.equals("1") ? true : null;
f.apply("0"); // false
f.apply("1"); // true
f.apply("2"); // expected: null, actual: NullPointerException
Run Code Online (Sandbox Code Playgroud)
但是这些代码块运行良好:
Supplier<Object> s = () -> null;
s.get(); // null
Run Code Online (Sandbox Code Playgroud)
和
Supplier<Object> s = () -> false ? false : null;
s.get(); // null
Run Code Online (Sandbox Code Playgroud)
或者有功能:
Function<String, Boolean> f = s -> {
if (s.equals("0")) return false;
else if (s.equals("1")) return true;
else return null;
};
f.apply("0"); // false
f.apply("1"); // true
f.apply("2"); // null
Run Code Online (Sandbox Code Playgroud)
我测试了两个Java版本:
~# java -version
openjdk版本"1.8.0_66-internal"OpenJDK运行时环境(build 1.8.0_66-internal-b01)OpenJDK 64位服务器VM(内置25.66-b01,混合模式)
C:\>java -version
java版"1.8.0_51"Java(TM)SE运行时环境(版本1.8.0_51-b16)Java HotSpot(TM)64位服务器VM(版本25.51-b03,混合模式)
这与lambda表达式无关; 在这种情况下boolean,简单地说三元运算符的返回类型是,因此将使用自动拆箱.
NPE也被抛到这里:
public class Main {
private static Object method() {
return false ? false : false ? false : null;
}
public static void main(String[] args) {
System.out.println(method());
}
}
Run Code Online (Sandbox Code Playgroud)
那么,到底发生了什么?
首先,false ? false : null根据JLS§15.25评估'embedded'expression():
条件运算符在语法上是右关联的(它从右到左分组).因此,a?b:c?d:e?f:g表示与a b相同:(c?d:(e?f:g)).
类型嵌入表达的是Boolean(盒装boolean),这样既false和null可以放入它.
然后整个表达是:
false ? false : (Boolean expression)
Run Code Online (Sandbox Code Playgroud)
然后,再次根据JLS§15.25:
如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是将装箱转换(第5.1.7节)应用于T的结果,那么条件表达式的类型是T.
因此,第一个参数是原始类型boolean(T在规范中),另一个的类型是boxed T(Boolean),因此整个表达式的类型是boolean.
然后,在运行时,嵌入式表达式计算null自动取消装箱到哪个boolean,从而导致NPE.
| 归档时间: |
|
| 查看次数: |
477 次 |
| 最近记录: |