在 Java 中使用 if 与三元运算符时的“错误”返回类型
Posted
技术标签:
【中文标题】在 Java 中使用 if 与三元运算符时的“错误”返回类型【英文标题】:"Wrong" return type when using if vs. ternary opertator in Java 【发布时间】:2012-08-19 23:51:38 【问题描述】:在下面的类中,两个方法的返回类型与三元运算符的思想不一致:
return condition?a:b;
等价于
if(condition)
return a;
else
return b;
第一个返回一个 Double,第二个返回一个 Long:
public class IfTest
public static Long longValue = 1l;
public static Double doubleValue = null;
public static void main(String[] args)
System.out.println(getWithIf().getClass());// outpus Long
System.out.println(getWithQuestionMark().getClass());// outputs Double
public static Object getWithQuestionMark()
return doubleValue == null ? longValue : doubleValue;
public static Object getWithIf()
if (doubleValue == null)
return longValue;
else
return doubleValue;
我可以想象这与编译器窄转换 getWithQuestionMark()
的返回类型有关,但这种语言是否明智?这肯定不是我所期望的。
欢迎任何见解!
编辑:下面有很好的答案。此外,@sakthisundar 引用的以下问题探讨了在三元运算符中发生的类型提升的另一个副作用:Tricky ternary operator in Java - autoboxing
【问题讨论】:
之前已经提出过类似的问题,原因与 Jon Skeet 的回答相同。结帐this @sakthisundar 谢谢!您指向的问题是由相同的 answer 激发的,但是从 problem 开始时我找不到它。我现在直接在问题正文中引用了它 【参考方案1】:基本上是遵循section 15.25 of the JLS的规则,具体来说:
否则,如果第二个和第三个操作数具有可转换(第 5.1.8 节)为数字类型的类型,则有几种情况:
[...]
否则,二进制数值提升(第 5.6.2 节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。
所以遵循section 5.6.2,这将基本上涉及拆箱 - 所以这使您的表达式工作就像longValue
和doubleValue
分别是long
和double
类型一样,并且扩大提升适用于long
得到double
的整体结果类型。
然后将 double
装箱,以便从方法中返回 Object
。
【讨论】:
啊哈!所以,1+2
给出一个整数,1+2d
给出一个双精度数,同样:
会在可能的情况下进行数字提升。仍然不是我所期望的,但比它与返回类型有任何关系要好。谢谢!【参考方案2】:
除了@Jon 的回答,看看你看到的字节码:
public static java.lang.Object getWithQuestionMark();
Code:
0: getstatic #7; //Field doubleValue:Ljava/lang/Double;
3: ifnonnull 16
6: getstatic #8; //Field longValue:Ljava/lang/Long;
9: invokevirtual #9; //Method java/lang/Long.longValue:()J
12: l2d
13: goto 22
16: getstatic #7; //Field doubleValue:Ljava/lang/Double;
19: invokevirtual #10; //Method java/lang/Double.doubleValue:()D
22: invokestatic #11; //Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
25: astore_0
26: aload_0
27: areturn
如果你告诉编译器你对数字不感兴趣:
public static Object getWithQuestionMark()
return doubleValue == null ? (Object)longValue : (Object)doubleValue;
你会得到你想要的(字节码)
public static java.lang.Object getWithQuestionMark();
Code:
0: getstatic #7; //Field doubleValue:Ljava/lang/Double;
3: ifnonnull 12
6: getstatic #8; //Field longValue:Ljava/lang/Long;
9: goto 15
12: getstatic #7; //Field doubleValue:Ljava/lang/Double;
15: areturn
输出:
$ java IfTest
class java.lang.Long
class java.lang.Long
【讨论】:
只有一次向上转换到Object
就足够了。以上是关于在 Java 中使用 if 与三元运算符时的“错误”返回类型的主要内容,如果未能解决你的问题,请参考以下文章