具有自动装箱功能的三元运算符中的Java NPE?
今天早上我遇到了一个非常奇怪的NPE,并将其简化为一个简单的例子。这是 JVM 错误还是正确行为?
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)
$
I ran across a very weird NPE this morning, and reduced it to a simple example. Is this a JVM bug or correct behavior?
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()));
}
}
Output from compile and run:
$ javac Test1.java
$ java Test1
Exception in thread "main" java.lang.NullPointerException
at Test1.f(Test1.java:12)
at Test1.main(Test1.java:16)
$
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
表达式
item == null 的类型? 1:item.getId()
是int
而不是Integer
。因此,Java 需要自动将Integer
拆箱为int
(导致NullPointerException
)。然后它会自动将结果装箱为一个Integer
(如果没有NullPointerException
,它会)从方法返回。另一方面,表达式
item == null ? new Integer(1) :item.getId()
的类型为Integer
,不需要进行自动拆箱。当您自动取消装箱
null
Integer
时,您会收到NullPointerException
(请参阅 自动装箱),这就是您所经历的。回答你的问题,这是正确的行为。
The type of the expression
item == null ? 1 : item.getId()
isint
notInteger
. Therefore, Java needs to auto-unbox yourInteger
to anint
(causing theNullPointerException
). Then it auto-boxes the result back to anInteger
(well it would if not for theNullPointerException
) to return from the method.On the other hand, the expression
item == null ? new Integer(1) : item.getId()
has a type ofInteger
and no auto-unboxing needs to be done.When you auto-unbox a
null
Integer
, you get aNullPointerException
(see Autoboxing) and that is what you are experiencing.To answer your question, this is correct behavior.
如果你反编译类文件,你会清楚地看到你的 NPE...
If you decompile the class file you will see clearly your NPE...
item
可能不是null
,但是当您调用getId()
时,就会返回null
。当您尝试自动取消装箱null
时,您会收到 NPE。item
may not benull
, but when you callgetId()
, that is returningnull
. When you try to auto-unboxnull
, you get an NPE.下面的返回类型是
Integer
-以下结果 -
在您的情况下是
null
。因此,JVM 抛出 NPE 是因为它试图自动装箱
null
。尝试 -
两者都会抛出 NPE。
The return type below is
Integer
-And the result of the following -
is
null
in your case.So, JVM is throwing NPE because it is trying to autobox
null
.Try -
both will throw NPE.
发生这种情况是因为您使用了条件运算符
?
。行return item == null ? 1 : item.getId();
相当于
The result is int 因为表达式中的第一个操作数。这就是当您用 Integer 显式包装 1 时您的代码可以工作的原因。在这种情况下,编译器会创建类似
So, NPE 当尝试将 item.getId() (即 null)“转换”为 int 时发生。
It happens because you are using conditional operator
?
. Linereturn item == null ? 1 : item.getId();
is equivalent to
The result is int because of the first operand in your expression. This is the reason that your code works when you explicitly wrap 1 with Integer. In this case the compiler creates something like
So, NPE happens when attempting to "cast" item.getId() (that is null) to int.