为什么将Integer与int进行比较可以在Java中抛出NullPointerException? [英] Why comparing Integer with int can throw NullPointerException in Java?

查看:690
本文介绍了为什么将Integer与int进行比较可以在Java中抛出NullPointerException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

观察这种情况让我非常困惑:

It was very confusing to me to observe this situation:

Integer i = null;
String str = null;

if (i == null) {   //Nothing happens
   ...                  
}
if (str == null) { //Nothing happens

}

if (i == 0) {  //NullPointerException
   ...
}
if (str == "0") { //Nothing happens
   ...
}

所以,as我认为首先执行装箱操作(即java尝试从 null 中提取int值),并且比较操作具有较低的优先级,这就是抛出异常的原因。

So, as I think boxing operation is executed first (i.e. java tries to extract int value from null) and comparison operation has lower priority that's why the exception is thrown.

问题是:为什么在Java中以这种方式实现?为什么拳击优先于比较参考?或者为什么他们没有在拳击前对 null 实施验证?

The question is: why is it implemented in this way in Java? Why boxing has higher priority then comparing references? Or why didn't they implemented verification against null before boxing?

NullPointerException 被包装的基元抛出时,它看起来不一致,并且不会抛出 true 对象类型。

At the moment it looks inconsistent when NullPointerException is thrown with wrapped primitives and is not thrown with true object types.

推荐答案

简答



关键点是:

The Short Answer

The key point is this:


  • == 两种参考类型之间总是参考比较


    • 通常情况下,例如使用 Integer String ,您要使用等于

    • == between two reference types is always reference comparison
      • More often than not, e.g. with Integer and String, you'd want to use equals instead

      • 引用类型将进行拆箱转换

      • 拆箱 null 总是抛出 NullPointerException

      • The reference type will be subjected to unboxing conversion
      • Unboxing null always throws NullPointerException

      以上语句适用于任何给定的有效 Java代码。根据这种理解,您提供的代码段中没有任何不一致。

      The above statements hold for any given valid Java code. With this understanding, there is no inconsistency whatsoever in the snippet you presented.

      以下是相关的JLS部分:

      Here are the relevant JLS sections:


      JLS 15.21.3参考等式运算符 == !=



      如果等于运算符的操作数都是引用类型或 null 类型,然后操作是对象相等。

      JLS 15.21.3 Reference Equality Operators == and !=

      If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.

      这解释了以下内容:

      Integer i = null;
      String str = null;
      
      if (i == null) {   // Nothing happens
      }
      if (str == null) { // Nothing happens
      }
      if (str == "0") {  // Nothing happens
      }
      

      两个操作数是引用类型,这就是 == 是引用相等比较的原因。

      Both operands are reference types, and that's why the == is reference equality comparison.

      这也解释了以下内容: / p>

      This also explains the following:

      System.out.println(new Integer(0) == new Integer(0)); // "false"
      System.out.println("X" == "x".toUpperCase()); // "false"
      

      对于 == 为了数字相等,至少有一个操作数必须是数字类型


      JLS 15.21.1数值等式运算符 == !=



      如果等于运算符的操作数是两者的数字类型,或一个的数字类型和另一个是可转换的到数字类型,对操作数执行二进制数字提升。如果提升类型的操作数是 int long ,则执行整数相等测试;如果提升类型是 float或 double`,则执行浮点相等测试。

      JLS 15.21.1 Numerical Equality Operators == and !=

      If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible to numeric type, binary numeric promotion is performed on the operands. If the promoted type of the operands is int or long, then an integer equality test is performed; if the promoted type is float ordouble`, then a floating-point equality test is performed.

      注意二进制数字促销执行价值集转换和拆箱转换。

      Note that binary numeric promotion performs value set conversion and unboxing conversion.

      这解释了:

      Integer i = null;
      
      if (i == 0) {  //NullPointerException
      }
      

      以下摘录自 Effective Java 2nd Edition,第49项:首选原语为盒装基元


      总之,只要您有选择,就可以优先使用原始元素。原始类型更简单,更快捷。如果你必须使用盒装基元,小心!自动装箱减少了使用盒装基元的冗长度,但没有降低危险性。当您的程序将两个盒装基元与 == 运算符进行比较时,它会进行身份比较,这几乎肯定不是您想要的。当你的程序执行涉及盒装和未装箱原语的混合类型计算时,它会进行拆箱,当你的程序进行拆箱时,它会抛出 NullPointerException 。最后,当你的程序框原始值时,它可能导致昂贵和不必要的对象创建。

      In summary, use primitives in preference to boxed primitive whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations.

      有些地方你别无选择但要使用盒装基元,例如泛型,但你应该认真考虑是否有合理使用盒装基元的决定。

      There are places where you have no choice but to use boxed primitives, e.g. generics, but otherwise you should seriously consider if a decision to use boxed primitives is justified.

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆