代码对象o = true?new Integer(0):new Long(1)返回值为0的Long.为什么?

ars*_*tov 10 java

请考虑我们的代码如下:

Object obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + obj);
Run Code Online (Sandbox Code Playgroud)

其结果是:

class java.lang.Long
value = 0
Run Code Online (Sandbox Code Playgroud)

代替:

class java.lang.Integer
value = 0
Run Code Online (Sandbox Code Playgroud)

有人可以澄清为什么我们在Java中有这样的功能吗?这对我来说很奇怪.你有什么例子可以用吗?

更新:这是一段字节码,我们可以看到,那里有什么

NEW java/lang/Integer
DUP
LDC "0"
INVOKESPECIAL java/lang/Integer.<init> (Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/Integer.intValue ()I
I2L
INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
ASTORE 1
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 12

这里发生的是结果

  • 二进制数字提升将您的Integer和Long类型转换long为用作应用于条件运算符表达式的公共类型
  • 拆箱那些包装器对象
  • 然后装箱条件表达式的结果值

条件运算符的第二个和第三个操作数必须最终具有相同的类型,这是表达式的结果类型.Integer而Long不是,当然,同样的类型.

但是,如JLS§15.25中所述,编译器将在确定要应用于表达式的可能公共类型时应用二进制数字提升.该部分有一个方便的表15.25-D,告诉我们当第二个操作数是类型Integer而第三个操作数是类型时Long,编译器将进行二进制数字提升Integer,Long.Integer,Long收益率的二进制数字推广long.所以条件运算符表达式的结果是long.

由于表达式的结果类型是long,Integer或者Long必须取消装箱(然后在其情况下进行转换Integer).

最后,你将它分配给一个Object强制拳击,并包装long在一个Long.因此,您最终会得到一个与您的输出相匹配Long的值0.

如此有效,如果我们忽略了编译器将优化以下一半的事实,因为它处理一个常量表达式,这要归功于true代码(我在flag下面使用过),该代码最终会成为:

Object obj = Long.valueOf(flag ? (long)(new Integer(0)).intValue() : (new Long(1)).longValue());
System.out.println(obj.getClass() + "\nvalue = " + obj);
Run Code Online (Sandbox Code Playgroud)
  • 的(long)(new Integer(0)).intValue()代表的拆箱Integer和铸造它long因此它的表达结果类型相匹配.
  • 该(new Long(1)).longValue()代表拆箱的Long所以它的expresion结果类型相匹配.
  • 最后Long.valueOf代表拳击.