不同之处在于编译时表达式的静态类型:
概括
E1: `(false ? 1.0f : null)`
- arg 2 '1.0f' : type float,
- arg 3 'null' : type null
- therefore operator ?: : type Float (see explanation below)
- therefore autobox arg2
- therefore autobox arg3
E2: `(false ? 1.0f : (false ? 1.0f : null))`
- arg 2 '1.0f' : type float
- arg 3 '(false ? 1.0f : null)' : type Float (this expr is same as E1)
- therefore, outer operator ?: : type float (see explanation below)
- therefore un-autobox arg3
详细说明:
这是我通过阅读规范并从你得到的结果向后工作的理解。归结为 f2内部条件的第三个操作数的类型是 null 类型,而 f2外部条件的第三个操作数的类型被认为是 Float。
注意:重要的是要记住类型的确定和装箱/拆箱代码的插入是在编译时完成的。装箱/拆箱代码的实际执行是在运行时完成的。
Float f1 = (false ? 1.0f : null);
Float f2 = (false ? 1.0f : (false ? 1.0f : null));
f1 条件和 f2 内部条件:(false ? 1.0f : null)
f1 条件和 f2 内部条件是相同的:(false ? 1.0f : null)。f1 条件和 f2 内部条件中的操作数类型是:
type of second operand = float
type of third operand = null type (§4.1)
§15.25中的大多数规则都已通过,并且确实应用了此最终评估:
否则,第二个和第三个操作数分别是 S1 和 S2 类型。令 T1 为对 S1 应用装箱转换产生的类型,令 T2 为对 S2 应用装箱转换产生的类型。条件表达式的类型是将捕获转换 ( §5.1.10 ) 应用于 lub(T1, T2) ( §15.12.2.7 ) 的结果。
S1 = float
S2 = null type
T1 = Float
T2 = null type
type of the f1 and f2 inner conditional expressions = Float
因为对于 f1,赋值是对一个 Float 引用变量,所以表达式的结果 (null) 被成功赋值。
对于 f2 外部条件:(false ? 1.0f : [f2 内部条件])
对于 f2 外部条件,类型为:
type of second operand = float
type of third operand = Float
请注意操作数类型与直接引用null文字的 f1/f2 内部条件(第4.1 节)相比的差异。由于具有 2 种数字可转换类型的差异,因此适用§15.12.2.7中的这条规则:
由于对 f2 内部条件 (null) 的结果执行了拆箱转换,因此引发了 NullPointerException。