我正在尝试理解以下代码。第2行输出 null ,而第3行则抛出 NullPointerException 。我想念什么?从理论上讲,它应该起作用。
public static void main(String []args){
1 Object[] obj = {null};
2 System.out.println((Integer)obj[0]); //Output null
3 Integer n = obj[0] == null ? (Integer)obj[0] : 1; //NullPointerException
4 System.out.println(n);
}
答案 0 :(得分:10)
根据JLS中定义的规则,三元条件运算符的类型
null ? (Integer)obj[0] : 1;
是int
,而不是Integer
。
因此,当此表达式的结果为(Integer)obj[0]
时,Integer
会被取消装箱到int
中,并且您会得到NullPointerException
。
请参见JLS 15.25. Conditional Operator ? :,表15.25-A。 :
由于第二个操作数为Integer
,而第三个操作数为int
,因此条件表达式类型为int
。
答案 1 :(得分:3)
这里的关键概念是 binary numeric promotion 。
为运算符提供不同类型的操作数时,必须将这些操作数转换为彼此兼容。此转换的条件运算符规则相当复杂;但是,当操作数的类型不同并且可以转换为数字时,将应用二进制数字提升。
在提供一个装箱的和一个原始操作数的情况下,二进制数值提升的作用是尝试取消装箱的操作数,而不取消装箱的原始操作数。
您可以使用其他多操作数运算符(例如+
)来观察二进制数值的提升:
System.out.println(1 + (Integer) null); // NullPointerException!
使用条件运算符,如果您明确将1装箱,则不会获得NPE,因为操作数的类型不同:
Integer n = obj[0] == null ? (Integer)obj[0] : Integer.valueOf(1);