为什么Java编译器有时允许取消装箱为空?

例如:

int anInt = null; 

在编译时失败但是

 public static void main(String[] args) { for (int i = 0; i < 10; i++) { System.out.println("" + getSomeVal()); } } public static int getSomeVal() { return new Random().nextBoolean() ? 1 : null; } 

在运行时(通常)失败。 试图返回null也会导致编译错误,所以我假设有多个路径会导致编译器推断出null可能是一个自动装箱的int ? 为什么javac能够以相同的错误编译这两种情况?

在第一种情况下,编译器知道您正在尝试取消编译时的null编译时常量。

在第二种情况下,条件表达式的类型是Integer ,因此您可以有效地编写:

 Integer tmp = new Random().nextBoolean() ? 1 : null; return (int) tmp; 

…所以取消装箱不会发生在常量表达式上,编译器会允许它。

如果你改变它以通过在那里取消装箱强制条件表达式为int类型,它将失败:

 // Compile-time failure return new Random().nextBoolean() ? 1 : (int) null; 

Boxing部分隐藏了基元和相应的包装器对象之间的区别,但它并没有将其删除。

拳击没有改变有两个区别:

  • 对象可以为null,而基元则不能
  • 对象具有状态和标识,而基元只有状态(值)

偶尔,这些差异可能会导致使用拳击时出现问题。

有些要记住的要点:

  • 小心空值。 自动取消装箱空对象将导致NullPointerException
  • 比较项目与==equals必须小心。

您不能将null分配给int

  int anInt = null; 

Java允许这样做,因为您没有为int赋值null

  System.out.println("" + getSomeVal()); //null was just converted to a srting and was printed 

如果执行此操作,则可能会收到错误消息

  int anInt = getSomeVal();