eclipse 取消装箱空盒装对象会引发意外的 NullPointerException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14992077/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 20:02:05  来源:igfitidea点击:

Unboxing a null boxed object throws unexpected NullPointerException

javaeclipsenullpointerexceptionunboxing

提问by mre

If you run the following code,

如果运行以下代码,

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;
        }
    }
}

you will get the following stacktrace,

您将获得以下堆栈跟踪,

Exception in thread "main" java.lang.NullPointerException
    at Foo.main(Foo.java:3)

How come there's no compiler warning or anything? IMHO it's a pretty nasty subtlety with unboxing, or maybe I'm just naive.

为什么没有编译器警告或任何东西?恕我直言,拆箱是一个非常令人讨厌的微妙之处,或者我可能只是天真。



Adding on to the answer provided by @Javier, if you're using Eclipse, you need to do the following to enable this:

添加@Javier提供的答案,如果您使用的是 Eclipse,则需要执行以下操作以启用此功能:

  1. Navigate to Window> Preferences> Java> Compiler> Errors/Warnings
  2. Expand Potential programming problems
  3. Toggle Boxing and unboxing conversionsto either "Warning", or "Error"
  4. Tap "OK"
  1. 导航到Window> Preferences> Java> Compiler>Errors/Warnings
  2. 展开潜在的编程问题
  3. 装箱和拆箱转换切换为“警告”或“错误”
  4. 点击“确定”

采纳答案by Javier

I don't know what IDE are you using, but Eclipse has an option to enable warning on boxing and unboxing conversions. It is not possible to detect it as a null pointer access, since null is not immediatly unboxed, but via Bar.getId().

我不知道您使用的是什么 IDE,但 Eclipse 有一个选项可以在装箱和拆箱转换时启用警告。不可能将其检测为空指针访问,因为 null 不是立即拆箱,而是通过Bar.getId().

The expression of type Integer is unboxed into int
Foo.java line 3

Integer 类型的表达式被拆箱到 int
Foo.java 第 3 行

回答by ameed

If you try to use any method on a nullor do anything that does not make sense with a null, it throws a NullPointerException.

如果您尝试在 a 上使用任何方法null或执行任何对 a没有意义的事情null,它会抛出 a NullPointerException

Autounboxing is implemented with the [Integer object].intValue()method (or similar), so it throws a NullPointerExceptionbecause you can't have nullinvoke a method.

自动拆箱是用[Integer object].intValue()方法(或类似方法)实现的,所以它抛出 aNullPointerException因为你不能null调用一个方法。

Hope this helps!

希望这可以帮助!

回答by mre

it appears that this behavior is documented in the JDK™ 5.0 Documentation,

这种行为似乎记录在JDK™ 5.0 文档中

..you can largely ignore the distinction between intand Integer, with a few caveats. An Integerexpression can have a null value. If your program tries to autounbox null, it will throw a NullPointerException.

..你可以在很大程度上忽略的区别intInteger,有几个注意事项。一个Integer表达式可以有一个空值。如果您的程序尝试自动拆箱 null,它将抛出一个NullPointerException.

回答by seand

Boxing is nothing more than syntactical sugar for casting an object like Integer to the native equivalent 'int'. Natives can't be null but objects can. The boxing mechanism won't prevent NullPointerExceptions in these cases.

装箱只不过是将像 Integer 这样的对象转换为本机等效的“int”的语法糖。本机不能为空,但对象可以。在这些情况下,装箱机制不会阻止 NullPointerExceptions。

回答by lichengwu

NullPointerExceptionis a RuntimeExceptionthan IDE can not detect when compile the code.

NullPointerExceptionRuntimeExceptionIDE在编译代码时无法检测到的。

Instead, a good practice is check null before unboxing.

相反,一个好的做法是在拆箱前检查 null。

int getId(){
    if(id!=null){
        return id;
    }
    // return other or throw a checked exception.
}

回答by AgilePro

Seems like a perfectly reasonable run time exception. If your main code was:

似乎是一个完全合理的运行时异常。如果您的主要代码是:

public static void main(String[] args){        
    Integer idObj = new Bar().getId();
    int id = idObj;   // throws NullPointerException
}

Nobody would be surprised about the null pointer exception. The Bar class returns a null, and a null object pointer can not be turned into a simple value. The implementation of the Bar class might be changed to initialize the id to a non-null value. This block of code can be compiled independently from the Bar class, and so assumptions about the dynamic workings of the Bar class should certainly not be coded into this block of code.

没有人会对空指针异常感到惊讶。Bar 类返回空值,并且空对象指针无法转换为简单值。Bar 类的实现可能会更改为将 id 初始化为非空值。这个代码块可以独立于 Bar 类进行编译,因此关于 Bar 类的动态工作的假设当然不应该被编码到这个代码块中。

This is probably obvious, but the real solution is to use intfor the id member, instead of Integer. This, then, has no issue:

这可能是显而易见的,但真正的解决方案是使用intid 成员,而不是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;
    }
}

(But I suppose you already were aware of this :-) )

(但我想你已经意识到这一点了 :-) )