带自动装箱的三元运算符中的Java NPE?
今天早上我遇到了一个非常奇怪的NPE,并将其简化为一个简单的示例。这是JVM错误还是正确的行为带自动装箱的三元运算符中的Java NPE?,java,nullpointerexception,Java,Nullpointerexception,今天早上我遇到了一个非常奇怪的NPE,并将其简化为一个简单的示例。这是JVM错误还是正确的行为 public class Test1 { class Item { Integer id = null; public Integer getId() {return id;} } public Integer f() { Item item = new Item(); // this works:
public class Test1 {
class Item {
Integer id = null;
public Integer getId() {return id;}
}
public Integer f() {
Item item = new Item();
// this works:
//return item == null ? new Integer(1) : item.getId();
// NPE??
return item == null ? 1 : item.getId();
}
public static void main(String[] args) {
Test1 t = new Test1();
System.out.println("id is: " + String.valueOf(t.f()));
}
}
编译和运行的输出:
$ javac Test1.java
$ java Test1
Exception in thread "main" java.lang.NullPointerException
at Test1.f(Test1.java:12)
at Test1.main(Test1.java:16)
$
item
可能不是null
,但是当您调用getId()
时,它将返回null
。当您尝试自动取消装箱null
时,您会得到一个NPE。下面的返回类型是整数
-
public Integer f() {
Item item = new Item();
// this works:
//return item == null ? new Integer(1) : item.getId();
// NPE??
return item == null ? 1 : item.getId();
}
下面的结果是什么-
item == null ? 1 : item.getId()
在您的情况下为null
因此,JVM抛出NPE是因为它试图自动装箱null
试一试-
两者都将抛出NPE。如果您反编译类文件,您将清楚地看到您的NPE
return Integer.valueOf(item != null ? item.getId().intValue() : 1);
表达式
item==null的类型?1:item.getId()
是int
不是Integer
。因此,Java需要将您的整数
自动取消装箱为int
(导致NullPointerException
)。然后,它会自动将结果返回到一个整数
(如果不是NullPointerException
),从该方法返回
另一方面,表达式item==null?新整数(1):item.getId()的类型为Integer
,无需自动取消装箱
当您自动取消对null
Integer
的装箱时,您会得到一个NullPointerException
(请参阅),这就是您遇到的情况
回答您的问题,这是正确的行为。之所以发生这种情况,是因为您使用的是条件运算符?
。线
返回项==null?1:item.getId()代码>
相当于
int result = item == null ? 1 : item.getId();
return result;
由于表达式中的第一个操作数,结果为int。这就是当您显式地用整数包装1时代码工作的原因。在本例中,编译器创建如下内容
Integer result = item == null ? new Integer(1) : item.getId();
return result;
因此,NPE在尝试将item.getId()(即null)强制转换为int时发生。pst使用Integer.valueOf(1)
而不是newinteger(1)
,这是自动装箱的好方法。这就是为什么流行的最佳实践建议在包装器上使用基本类型。非常类似于您确定吗?getId返回一个正好为null的整数,因此不应该有自动装箱。如果你说的是真的,那么为什么返回新整数(1)
会使NPE消失呢?@Kevin使用新整数(1)
,第二个和第三个操作数都是整数
类型,所以这就是条件类型。对于1
,条件表达式的类型是int
,因此getId()
的返回值被取消绑定为int
。(查看JLS的第15.25节,了解关于这方面的确切规则。)
Integer result = item == null ? new Integer(1) : item.getId();
return result;