java 条件运算符_Java 条件运算符?:

一、引言

无意中在StackOverflow上看到有人提出的一个问题:

Float f1 = false? 1.0f: null;

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

为什么f1是null而第二个语句抛出NullPointerException?

这就涉及到Java中常用的条件操作符?:。

二、背景知识

条件运算符?:使用一个表达式的boolean值来决定应该计算另外两个表达式中的哪个表达式。它是右结合的(即从右到左进行计算),因此a?b:c?d:e?f:g等同于a?b:(c?d:(e?f:g))。

条件运算符有3个操作数表达式。"?"出现在第一个和第二个表达式之间,而":" 出现在第二个和第三个表达式之间。

注意,第一个表达式必须是boolean或Boolean类型,否则会产生编译错误。而且让第二个或第三个操作数表达式调用一个void方法也会产生编译错误。

条件表达式的类型按照如下规则来确定:

•如果第二个和第三个操作数具有相同的类型(该类型可能是一个空类型),那么它就是条件表达式的类型。

•如果第二个和第三个操作数中的一个是基本类型T,另一个是对T进行装箱的结果类型,那么条件表达式的类型就是T。

•如果第二个和第三个操作数中的一个是空类型,另一个是引用类型,那么条件表达式的类型就是该引用类型。

•否则,如果第二个和第三个操作数中有可转换为数值类型的类型,那么就有这几种情形:

♦若操作数之一是byte或Byte类型,另一个是short或Short类型,那么条件表达式的类型就是short。

♦若操作数之一是T类型,其中T是byte、short或char,另一个操作数是int类型的常量表达式,其值可用类型T表示,那么条件表达式的类型是T。

♦若操作数之一是T类型,其中T是Byte、Short或Character,另一个操作数是为int类型的常量表达式,其值可用类型U表示,U是对T进行拆箱的结果,那么条件表达式的类型是U。

♦否则,二元数值提升(binary numeric promotion)会被应用于操作数类型,并且条件表达式的类型是第二个和第三个操作数提升后的类型。注意,二元数值提升执行值集转换且可能执行拆箱转换 。

•否则,第二个和第三个操作数的类型分别是S1和S2。令T1是对S1进行装箱转换的结果类型,T2是对S2进行装箱转换的结果类型。条件表达式的类型就是对lub(T1, T2)进行捕获转换的结果。

在运行期,条件表达式的第一个操作数表达式首先进行计算。如有必要,会在结果上执行拆箝转换。随后计算所选择的操作数表达式,并且将结果转换为按上面指定规则所确定的条件表达式的类型。这个转换可能包括装箱或拆箱转换。

声明:以上内容是本人翻译自《The Java® LanguageSpecification Java SE 7 Edition》2013-02-28这一版并截取了其中的一部分。

三、回归最开始的问题

首先要说明的是条件表达式结果类型的确定以及装箱/拆箱代码的插入是编译期完成的。装箱/拆箱代码的执行是在运行期完成的。

我将上述两行代码编译后,然后进行反编译,结果如下:

Float localFloat1 = (Float)null;

Float localFloat2 = Float.valueOf(((Float)null).floatValue());

很明显可以看到第二行中对null调用了拆箱方法floatValue(),所以抛出了NullPointerException。

下面来仔细分析一下:

(false ? 1.0f : null)这个表达式是第一个和第二个语句都有的,该表达式中第二个操作数的类型是float、第三个操作数的类型是null,所以可以应用下面这条规则:

否则,第二个和第三个操作数的类型分别是S1和S2。令T1是对S1进行装箱转换的结果类型,T2是对S2进行装箱转换的结果类型 。条件表达式的类型就是对lub(T1, T2)进行捕获转换的结果。

所以:  S1 = float

S2 = null

T1 = Float

T2 = null

那么条件表达式(false ? 1.0f : null)的类型 = Float

对于f1, 表达式的结果null成功赋值给一个Float引用变量。

对于f2,现在第二个操作数的类型为float,第三个操作数的类型是Float(参见上述分析),所以接下来可对其应用如下规则:

如果第二个和第三个操作数中的一个是基本类型T,另一个是对T进行装箱的结果类型,那么条件表达式的类型就是T。

所以f2最终的类型为float,则先要对选择的第三个操作数(null)执行拆箱操作,然后再执行装箱操作,在拆箱过程中产生NullPointerException。

四、总结

混合类型的计算会引起混乱,在条件运算符?:中表现的尤为明显,所以建议在条件表达式中保持第二个和第三个操作数的类型相同。

五、参考资料

《The Java® LanguageSpecification Java SE 7 Edition》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值