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

Mil*_*son 16 java unboxing compilation javac

例如:

int anInt = null;
Run Code Online (Sandbox Code Playgroud)

在编译时失败但是

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;
}
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 20

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

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

Integer tmp = new Random().nextBoolean() ? 1 : null;
return (int) tmp;
Run Code Online (Sandbox Code Playgroud)

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

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

// Compile-time failure
return new Random().nextBoolean() ? 1 : (int) null;
Run Code Online (Sandbox Code Playgroud)