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

2022-09-03 06:05:58

例如:

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;
}

在运行时(通常)失败。尝试返回也会导致编译错误,所以我假设有多个路径会导致编译器推断出可能是自动装箱的?为什么javac不能失败编译两个案例具有相同的错误?nullnullint


答案 1

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

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

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

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

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

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

答案 2

Boxing 部分隐藏了基元和相应包装对象之间的区别,但它不会删除它。

有两个区别不会因拳击而改变:

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

有时,这些差异可能会导致使用装箱时出现问题。

要记住的几点:

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

推荐