if语句在java中使用if vs.三值运算符时的“错误”返回类型

7xzttuei  于 2021-07-09  发布在  Java
关注(0)|答案(2)|浏览(328)

在下面的类中,两个方法的返回类型与三元运算符的思想不一致:

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引用的以下问题探讨了三元运算符中类型提升的另一个副作用:java-autoboxing中棘手的三元运算符

khbbv19g

khbbv19g1#

除了@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
nvbavucw

nvbavucw2#

基本上它遵循jls第15.25节的规则,特别是:
否则,如果第二个和第三个操作数的类型是可转换的(§5.1.8)对于数字类型,则有几种情况:
[...]
否则,二进制数字提升(§5.6.2)应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。
接下来是第5.6.2节,它将基本上涉及到拆箱-所以这使您的表达式工作得好像 longValue 以及 doubleValue 属于 long 以及 double 分别进行加宽促销 long 要获得类型的总体结果 double .
那个 double 然后装箱以退回 Object 从方法上。

相关问题