Bal*_*usC 128 java autoboxing boolean nullpointerexception conditional-operator
为什么这会抛出 NullPointerException
public static void main(String[] args) throws Exception {
Boolean b = true ? returnsNull() : false; // NPE on this line.
System.out.println(b);
}
public static Boolean returnsNull() {
return null;
}
Run Code Online (Sandbox Code Playgroud)
虽然这不是
public static void main(String[] args) throws Exception {
Boolean b = true ? null : false;
System.out.println(b); // null
}
Run Code Online (Sandbox Code Playgroud)
?
解决办法是更换的方式false通过Boolean.FALSE,以避免null被拆箱到boolean,可呈现是不可能的.但这不是问题.问题是为什么?JLS中是否有任何引用证实了这种行为,尤其是第二种情况?
Ber*_*t F 90
区别在于方法的显式类型returnsNull()会影响编译时表达式的静态类型:
E1: `true ? returnsNull() : false` - boolean (auto-unboxing 2nd operand to boolean)
E2: `true ? null : false` - Boolean (autoboxing of 3rd operand to Boolean)
Run Code Online (Sandbox Code Playgroud)
对于E1,该类型的第二和第三个操作数是Boolean和boolean分别,故该条款适用:
如果第二个和第三个操作数之一是boolean类型,另一个类型是Boolean类型,那么条件表达式的类型是boolean.
由于表达式的类型是boolean,第二个操作数必须被强制转换为boolean.编译器将自动拆箱代码插入第二个操作数(返回值returnsNull())以使其键入boolean.这当然会导致NPE null在运行时返回.
对于E2,第2和第3个操作数的类型<special null type>(分别不是Boolean在E1!中)boolean,因此不适用特定的输入子句(去读它们!),因此最终的"其他"条款适用:
否则,第二和第三操作数分别是S1和S2类型.设T1是将拳击转换应用于S1所产生的类型,让T2为应用到S2的装箱转换所产生的类型.条件表达式的类型是将捕获转换(第5.1.10节)应用于lub(T1,T2)(第15.12.2.7节)的结果.
<special null type>(见§4.1)boolean<special null type>(参见§5.1.7中拳击转换列表中的最后一项 )Boolean所以条件表达式的类型是Boolean,第三个操作数必须被强制转换Boolean.编译器为第3个操作数(false)插入自动装箱代码.第二个操作数不需要自动取消装箱E1,因此null返回时不会自动取消装箱NPE .
这个问题需要类似的类型分析:
jju*_*kel 25
这条线:
Boolean b = true ? returnsNull() : false;
Run Code Online (Sandbox Code Playgroud)
内部转变为:
Boolean b = true ? returnsNull().booleanValue() : false;
Run Code Online (Sandbox Code Playgroud)
执行拆箱; 因此:null.booleanValue()将产生NPE
这是使用自动装箱时的主要缺陷之一.这种行为确实记录在5.1.8 JLS中
编辑:我认为拆箱是由于第三个运算符是布尔类型,如(隐式强制转换):
Boolean b = (Boolean) true ? true : false;
Run Code Online (Sandbox Code Playgroud)
axt*_*avt 16
- 如果第二个和第三个操作数之一是boolean类型,另一个类型是Boolean类型,那么条件表达式的类型是boolean.
所以,第一个例子试图调用Boolean.booleanValue(),以转化Boolean到boolean按第一条规则.
在第二种情况下,第一个操作数是null类型,当第二个操作数不是引用类型时,应用自动装箱转换:
- 否则,第二和第三操作数分别是S1和S2类型.设T1是将拳击转换应用于S1所产生的类型,让T2为应用到S2的装箱转换所产生的类型.条件表达式的类型是将捕获转换(第5.1.10节)应用于lub(T1,T2)(第15.12.2.7节)的结果.
| 归档时间: |
|
| 查看次数: |
18124 次 |
| 最近记录: |