Unboxing a null boxed object throws unexpected NullPointerException

匿名 (未验证) 提交于 2019-12-03 08:48:34

问题:

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:

  1. Navigate to Window > Preferences > Java > Compiler > Errors/Warnings
  2. Expand Potential programming problems
  3. Toggle Boxing and unboxing conversions to either "Warning", or "Error"
  4. Tap "OK"

回答1:

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().

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



回答2:

it appears that this behavior is documented in the ,

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



回答3:

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

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

Hope this helps!



回答4:

NullPointerException is a RuntimeException than IDE can not detect when compile the code.

Instead, a good practice is check null before unboxing.

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


回答5:

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.

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

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 :-) )



回答6:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!