如果您运行以下代码,
public class Foo{
public static void main(String[] args){
int id = new Bar().getId(); // throws unexpected NullPointerException
}
private static class Bar{
private final Integer id;
public Bar(){
this(null);
}
public Bar(Integer id){
this.id = id;
}
public Integer getId(){
return id;
}
}
}
您将获得以下堆栈跟踪,
Exception in thread "main" java.lang.NullPointerException
at Foo.main(Foo.java:3)
为什么没有编译器警告或任何东西?恕我直言,这是一个非常讨厌的微妙与拆箱,或者也许我只是天真。
添加@Javier提供的答案,如果您使用的是Eclipse,则需要执行以下操作来启用此功能:
答案 0 :(得分:5)
我不知道您使用的是什么IDE,但Eclipse可以选择在装箱和拆箱转换时启用警告。无法将其检测为空指针访问,因为null不是立即取消装箱,而是通过Bar.getId()
。
Integer类型的表达式被取消装入int中 Foo.java第3行
答案 1 :(得分:5)
如果您尝试在null
上使用任何方法或使用null
执行任何无意义的操作,则会抛出NullPointerException
。
Autounboxing使用[Integer object].intValue()
方法(或类似方法)实现,因此它会抛出NullPointerException
,因为您无法null
调用方法。
希望这有帮助!
答案 2 :(得分:4)
..你可以在很大程度上忽略
int
和Integer
之间的区别 一些警告。Integer
表达式可以具有空值。如果你的 程序尝试autounbox null,它将抛出NullPointerException
。
答案 3 :(得分:0)
NullPointerException
是一个RuntimeException
,而不是IDE在编译代码时无法检测到的。
相反,一个好的做法是在取消装箱之前检查null。
int getId(){
if(id!=null){
return id;
}
// return other or throw a checked exception.
}
答案 4 :(得分:0)
似乎是一个非常合理的运行时异常。如果您的主要代码是:
public static void main(String[] args){
Integer idObj = new Bar().getId();
int id = idObj; // throws NullPointerException
}
没有人会对空指针异常感到惊讶。 Bar类返回null,并且无法将null对象指针转换为简单值。可以更改Bar类的实现以将id初始化为非null值。这个代码块可以独立于Bar类编译,因此关于Bar类动态工作的假设当然不能编码到这个代码块中。
这可能很明显,但真正的解决方案是使用int
作为id成员,而不是Integer
。那么,这没有问题:
private static class Bar{
private final int id;
public Bar(){
this(0);
}
public Bar(int id){
this.id = id;
}
public int getId(){
return id;
}
}
(但我想你已经意识到了这一点:-))
答案 5 :(得分:0)
拳击只不过是用于将像Integer这样的对象投射到其中的语法糖 原生等价'int'。原生不能为null,但对象可以。在这些情况下,装箱机制不会阻止NullPointerExceptions。