java条件运算符(?:),Java条件运算符?:结果类型

本文详细解析了Java中条件运算符的工作原理,并通过具体的例子解释了为何某些表达式会导致NullPointerException。文章对比分析了两个相似但行为不同的条件运算符表达式,深入探讨了静态类型检查在编译时的作用。
摘要由CSDN通过智能技术生成

I'm a bit puzzled about the conditional operator. Consider the following two lines:

Float f1 = false? 1.0f: null;

Float f2 = false? 1.0f: false? 1.0f: null;

Why does f1 become null and the second statement throws a NullPointerException?

Langspec-3.0 para 15.25 sais:

Otherwise, the second and third operands are of types S1 and S2 respectively.

Let T1 be the type that results from applying boxing conversion to S1, and let

T2 be the type that results from applying boxing conversion to S2. The type of

the conditional expression is the result of applying capture conversion

(§5.1.10) to lub(T1, T2) (§15.12.2.7).

So for false?1.0f:null T1 is Float and T2 is the null type. But what is the result of lub(T1,T2)? This para 15.12.2.7 is just a bit too much ...

BTW, I'm using 1.6.0_18 on Windows.

PS: I know that Float f2 = false? (Float) 1.0f: false? (Float) 1.0f: null; doesn't throw NPE.

解决方案

The difference is static typing of the expressions at compile time:

Summary

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

Detailed Explanation:

Here's my understand from reading through the spec and working backwards from the result you got. It comes down to the type of the third operand of the f2 inner conditional is null type while the type of the third operand of the f2 outer conditional is deemed to be Float.

Note: Its important to remember that the determination of type and the insertion of boxing/unboxing code is done at compile-time. Actual execution of boxing/unboxing code is done at run-time.

Float f1 = (false ? 1.0f : null);

Float f2 = (false ? 1.0f : (false ? 1.0f : null));

The f1 conditional and the f2 inner conditional: (false ? 1.0f : null)

The f1 conditional and the f2 inner conditional are identical: (false ? 1.0f : null). The operand types in the f1 conditional and the f2 inner conditional are:

type of second operand = float

type of third operand = null type (§4.1)

Most of the rules in §15.25 are passed up and this final evaluation is indeed applied:

Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (§5.1.10) to 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

Since for f1, the assignment is to a Float reference variable, the result of the expression (null) is successfully assigned.

For f2 outer conditional: (false ? 1.0f : [f2 inner conditional])

For the f2 outer conditional, the types are:

type of second operand = float

type of third operand = Float

Note the difference in operand types compared to the f1/f2 inner conditionals that reference the null literal directly (§4.1). Because of this difference of having 2 numeric-convertible types, this rule from §15.12.2.7 applies:

Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases: ...

Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands. Note that binary numeric promotion performs unboxing conversion (§5.1.8) and value set conversion (§5.1.13).

Because of the unboxing conversion performed on the result of the f2 inner conditional (null), a NullPointerException is raised.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值