8

可能的重复项:
布尔值、条件运算符和自动装箱
Java、Google 集合库;抽象迭代器的问题?

下面的代码产生一个 NPE:

Integer test = null;
Integer test2 = true ? test : 0;
System.out.println(test2);

要正确打印出“null”而不出现异常,需要以下代码:

Integer test = null;
Integer test2 = true ? test : (Integer)0;
System.out.println(test2);

在第一个示例中很明显,“test”正在被拆箱(转换为原生 int),但为什么呢?为什么更改三元运算符中的另一个表达式(如第二个示例)会修复它?谁能提供某种叙述,说明这两个示例中的内容是何时、什么以及为什么被装箱和拆箱?

4

1 回答 1

19

Java 语言规范的第 15.25 节

条件表达式的类型确定如下:

  • 如果第二个和第三个操作数的类型相同(可能是 null 类型),那么这就是条件表达式的类型。
    • 如果第二个和第三个操作数之一是布尔类型,另一个是布尔类型,则条件表达式的类型是布尔类型。
    • 如果第二个和第三个操作数之一是空类型,另一个是引用类型,那么条件表达式的类型就是那个引用类型。
    • 否则,如果第二个和第三个操作数具有可转换(第 5.1.8 节)为数字类型的类型,则有以下几种情况:
      • 如果其中一个操作数是 byte 或 Byte 类型,而另一个是 short 或 Short 类型,则条件表达式的类型是 short。
      • 如果其中一个操作数是 T 类型,其中 T 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式,其值可以用 T 类型表示,则条件表达式的类型是 T。
      • 如果其中一个操作数是 Byte 类型,而另一个操作数是 int 类型的常量表达式,其值可以用 byte 类型表示,则条件表达式的类型是 byte。
      • 如果其中一个操作数是 Short 类型,而另一个操作数是 int 类型的常量表达式,其值可以用 short 类型表示,则条件表达式的类型是 short。
      • 如果其中一个操作数是类型;字符和另一个操作数是一个int类型的常量表达式,它的值可以用char类型表示,那么条件表达式的类型就是char。
      • 否则,二进制数值提升(第 5.6.2 节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。请注意,二进制数字提升执行拆箱转换(第 5.1.8 节)和值集转换(第 5.1.13 节)。

所以它遵循最后一个项目符号,执行二进制数字提升,执行拆箱转换。因此,条件运算符表达式的类型是int,即使您将其分配给Integer. 它试图在 上执行拆箱转换null,因此出现异常。

于 2010-10-28T17:51:37.903 回答