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个操作数表达式。"?"出现在第一个和第二个表达式之间,而":" 出现在第二个和第三个表达式之间

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

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

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

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

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

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

             ♦操作数之一是byteByte类型另一个shortShort类型那么条件表达式的类型就是short。

             ♦操作数之一是T类型,其中Tbyte、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® Language  Specification 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® Language  Specification Java SE 7 Edition》

        http://stackoverflow.com/questions/2615498/java-conditional-operator-result-type


转载于:https://my.oschina.net/jackieyeah/blog/207709

<think>嗯,用户想了解条件运算符?:。首先,我需要回忆一下条件运算符的基本概念。条件运算符是C语言中的三元运算符,对吧?它的语法是条件 ? 表达式1 : 表达式2。当条件为真时,返回表达式1的值,否则返回表达式2的值。 接下来,得考虑用户可能的背景。他们可能是刚开始学编程的新手,所以需要解释得简单明了。应该先说明它为什么叫三元运算符,因为有三个操作数。然后举一个例子,比如比较两个数的大小,这样容易理解。 然后,要强调它的优点,比如简化代码,替代简单的if-else语句。但也要提醒注意事项,比如不要嵌套太多,影响可读性。可能用户在实际使用中会遇到滥用的情况,所以这部分很重要。 还要注意用户的问题是用中文回答,所以例子和解释都要用中文。另外,用户提到了系统级指令,要求数学表达式用$...$,但这里可能更多是代码示例,不过如果有数学相关的内容,比如比较数值,可能需要用LaTeX格式,但例子中的代码应该用代码块标出。 需要检查语法是否正确,比如运算符的优先级问题,是否需要加括号。比如在复杂的表达式中,用户可能容易出错,所以举例子的时候可以提到括号的使用。 可能用户还会想知道和其他运算符的区别,或者适用场景。比如在赋值语句中使用,或者在返回值时使用。例如,函数返回时根据条件选择不同的值。 有没有其他需要注意的地方?比如类型转换,如果表达式1和表达式2的类型不同,会发生什么?不过对于初学者来说,可能不需要太深入,但可以稍微提一下。 总结结构的话,应该分点介绍:定义、语法结构、实例、优点、注意事项。这样结构清晰,符合用户要求的逐步解决问题。 最后,确认是否覆盖了用户的需求,有没有遗漏的部分。比如用户可能想知道这个运算符在哪些编程语言中存在,不过问题中提到了C语言,所以可能主要围绕C系语言,但也可以提及其他语言的支持情况,比如JavaJavaScript等。</think>条件运算符(`?:`)是编程语言中一种**三元运算符**(需要三个操作数),主要用于简化条件判断和赋值操作。以下从多个维度逐步解析: --- ### 一、基本定义 - **中文名称**:条件运算符(或三目运算符) - **符号组成**:由 `?` 和 `:` 组合构成 - **语法格式**: ```c 条件表达式 ? 表达式1 : 表达式2 ``` - **执行逻辑**: 1. 若 `条件表达式` 为真(true),则返回 `表达式1` 的值 2. 若 `条件表达式` 为假(false),则返回 `表达式2` 的值 --- ### 二、实例解析 #### 例1:基础比较 ```c int a = 5, b = 3; int max = (a > b) ? a : b; // max = 5 ``` - **逻辑分解**: - 若 `a > b` 成立,`max` 赋值为 `a` - 否则赋值为 `b` #### 例2:嵌套使用(需谨慎) ```c int x = 10; char* result = (x > 0) ? "正数" : (x == 0) ? "零" : "负数"; ``` - **逻辑分解**: 1. 外层判断 `x > 0`,若成立返回 "正数" 2. 若外层不成立,进入内层判断 `x == 0`,成立返回 "零",否则返回 "负数" --- ### 三、核心优势 1. **代码简洁** 替代简单 `if-else` 结构,例如: ```c // 条件运算符 int abs_value = (num >= 0) ? num : -num; // 等效 if-else if (num >= 0) { abs_value = num; } else { abs_value = -num; } ``` 2. **表达式内联** 可直接嵌入到复杂表达式中,如函数参数、数学运算等: ```c printf("%s\n", (score >= 60) ? "及格" : "不及格"); ``` --- ### 四、注意事项 1. **优先级问题** 条件运算符优先级较低,建议用括号明确逻辑: ```c int y = (a > b) ? (a + 1) : (b - 1); // 正确写法 ``` 2. **可读性限制** 避免过度嵌套,例如: ```c // 不推荐写法 int z = (a > b) ? ((c > d) ? e : f) : g; ``` 3. **类型一致性** `表达式1` 和 `表达式2` 的类型应兼容,否则可能引发隐式类型转换: ```c double value = (flag) ? 3 : 2.5; // 3 会被转换为 3.0 ``` --- ### 五、典型应用场景 1. **简单条件赋值** ```c int discount = (isMember) ? 20 : 0; ``` 2. **返回值选择** ```c return (temperature > 30) ? "炎热" : "舒适"; ``` 3. **宏定义中的简化** ```c #define MAX(a, b) ((a) > (b) ? (a) : (b)) ``` --- ### 六、语言支持 - **广泛适用性**:C/C++、JavaJavaScript、Python(需语法调整)等均支持条件运算符 - **Python的特殊写法**: ```python result = a if condition else b ``` --- ### 总结 条件运算符通过紧凑的语法实现快速条件判断,但需在简洁性和可读性之间权衡。合理使用可提升代码效率,滥用则会导致维护困难。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值