我的应用程序(简化版)中有这段代码:
Object result;
if (check)
result = new Integer(1);
else
result = new Double(1.0);
System.out.println(result);
return result;
然后我决定将if-else语句重构为三元条件表达式,以便我的代码更简洁:
Object result = check ? new Integer(1) : new Double(1.0);
System.out.println(result);
return result;
事实证明,如果检查是true
,则两个版本会打印出不同的结果:
1
或:
1.0
不是三元条件等价于相应的if-else?
答案 0 :(得分:25)
if / else和条件(三元)表达式不完全等同于。条件表达式的结果必须具有类型。
您正在观察数字类型提升(或类型强制)的效果。
以下是语言规范的摘录(参见here),来自描述条件表达式返回值的部分:
否则,如果第二个和第三个操作数的类型可以转换(第5.1.8节)到数字类型,那么有几种情况:
最后这种情况是(我在这里省略了其他情况):
否则,二进制数字提升(第5.6.2节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。
以下是与二进制数字促销相关的其他规范:
应用扩展基元转换(第5.1.2节)来转换以下规则指定的一个或两个操作数:
- 如果任一操作数的类型为double,则另一个操作数将转换为double。
这是第一种情况(以下案例省略)。 double
总是胜利。
因此,无论条件表达式中第2和第3个操作数的顺序如何,表达式的返回类型都将提升为double
。
答案 1 :(得分:6)
简而言之,三元运算符与其他涉及数字类型提升的运算符没有区别。
当你有System.out.println(1 + 1.0)
之类的东西时,你希望它打印2.0
,因为输出中使用的操作数受数字类型提升的影响。
与三元运算符完全相同:System.out.println(true ? 1 : 1.0)
在执行与1.0
表达式相同的数字类型提升后将打印1 + 1.0
。
它的工作方式非常简单:运算符结果的类型应该在编译时知道,而实际结果是在运行时确定的。
答案 2 :(得分:4)
简短回答
第一个示例明确键入为Object
,导致向上播放。
第二个示例隐式输入为Double
,这会导致数字扩展。
答案很长
在Object
的示例中,没有值转换,只有转发,并且打印了1。
Object result;
if (1 == 1)
result = new Integer(1);
else
result = new Double(1.0);
如果您使用Double
声明,则会扩大并打印1.0。
Double result;
if (1 == 1)
result = new Integer(1);
else
result = new Double(1.0);
由于存在明确的类型,因此这些非常简单。
然而,三元表达式没有明确的类型,规则也不重要。
条件表达式的类型确定如下:
如果第二个和第三个操作数具有相同的类型(可能是null类型),那么这就是条件表达式的类型。
如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是将装箱转换(第5.1.7节)应用于T的结果,那么条件表达式的类型是吨。
如果第二个和第三个操作数之一是null类型而另一个操作数的类型是引用类型,则条件表达式的类型是该引用类型。
否则,如果第二个和第三个操作数的类型可转换(第5.1.8节)到数字类型,则有几种情况:
如果其中一个操作数的类型为字节或字节,另一个操作数的类型为short或Short,则条件表达式的类型很短。
如果其中一个操作数是T类型,其中T是byte,short或char,另一个操作数是int类型的常量表达式(第15.28节),其值可以在类型T中表示,那么条件表达式的类型是T.
如果其中一个操作数是T类型,其中T是Byte,Short或Character,另一个操作数是int类型的常量表达式(第15.28节),其值可以在类型U中表示。是将取消装箱转换应用于T的结果,则条件表达式的类型为U.
否则,二进制数字提升(第5.6.2节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。请注意,二进制数字促销执行值集转换(第5.1.13节)并可执行拆箱转换(第5.1.8节)。
否则,第二个和第三个操作数分别为S1和S2类型。设T1是将拳击转换应用于S1所产生的类型,让T2为应用到S2的装箱转换所产生的类型。条件表达式的类型是将捕获转换(第5.1.10节)应用于lub(T1,T2)(§15.12.2.7)的结果。
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25
数字Integer
和Double
的“推广类型”是Double
。
答案 3 :(得分:2)
除了@ pb2q回答
您可以将其验证为
public class test {
public static void main(String[] args) {
Object result;
Boolean check = true;
if (check)
result = new Integer(1);
else
result = new Double(1.0);
System.out.println(result);
result = check ? new Integer(2) : new Double(1.0);
System.out.println(result);
}
}
由于数字促销,它将打印2.0而不是2
答案 4 :(得分:1)
除了现有答案之外,您还可以通过特定的方式转换为所需类型来避免此问题:
Object result = args.length < 100 ? (Object)2 : (Object)1.0;
将整数作为整数转换为Object
,将双精度转换为双精度。 &#34;:&#34;两侧的表达式然后都是Object
类型,因此编译器不需要生成任何进一步的转换。