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

时间:2012-08-10 08:21:04

标签: java compilation javac unboxing

例如:

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能够以相同的错误编译这两种情况?

3 个答案:

答案 0 :(得分:20)

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

在第二种情况下,条件表达式的类型是Integer,所以你有效地写了:

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

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

如果您通过取消装箱 来更改它以强制条件表达式为int类型,则会失败:

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

答案 1 :(得分:2)

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

拳击没有改变两个区别:

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

有时候,这些差异会在使用拳击时引起问题。

要记住一些要点:

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

答案 2 :(得分:1)

您不能将null赋给int

    int anInt = null;

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

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

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

    int anInt = getSomeVal();