本问题已经有最佳答案,请猛点这里访问。
请考虑以下代码:
Object obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() +"
value =" + obj);
其结果是:
class java.lang.Long
value = 0
代替:
class java.lang.Integer
value = 0
有人可以澄清为什么我们在Java中具有这种功能吗? 对我来说很奇怪。
您是否有任何示例在其中可能有用?
更新:
这是一段字节码,我们可以看到那里发生了什么
NEW java/lang/Integer
DUP
LDC"0"
INVOKESPECIAL java/lang/Integer. (Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/Integer.intValue ()I
I2L
INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
ASTORE 1
为了使三元语句有效,双方应返回相同类型的值
@PeterLawrey Object o = false ? new Long(0) : new Integer(1);也将返回class java.lang.Long和1。 它不是最后一个参数的类型,而是可以通过扩展接收的类型。
当经过认真研究的问题获得很多好评时,我会喜欢上它。 但是如今阅读JLS实在是太多了...
为了澄清,这是为什么三元运算符意外地转换整数?的重复,而不是另一个。
另请参阅stackoverflow.com/questions/25230171/和稍微相关的stackoverflow.com/questions/8098953/
这是怎么回事
二进制数值提升将您的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中。因此,您最终得到一个包含值0的Long,该值与您的输出匹配。
如此有效,如果我们忽略了以下事实,由于代码中的true(我在下面使用了flag),编译器将处理以下常量表达式,因为它处理的是常量表达式,该代码最终将这个:
Object obj = Long.valueOf(flag ? (long)(new Integer(0)).intValue() : (new Long(1)).longValue());
System.out.println(obj.getClass() +"
value =" + obj);
(long)(new Integer(0)).intValue()表示将Integer拆箱并将其强制转换为Long,因此它与表达式结果类型匹配。
(new Long(1)).longValue()表示将Long拆箱,因此它与表达式结果类型匹配。
Long.valueOf表示最后的拳击。
JLS-15.25中对此行为进行了很好的解释。条件运算符? ::
The conditional operator has three operand expressions. ? appears between the first and second expressions, and : appears between the second and third expressions.
[...]
The type of a conditional expression is determined as follows:
[...]
Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:
[...]
Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.
这与三元运算符的工作方式有关。
:两侧的操作数必须具有兼容的类型,因此您不能具有以下类型:
true ? 1 :"Hello"
由于int和String不能隐式地相互转换。
但是,根据您的情况,类型是兼容的! int可以隐式转换为Long。这就是编译器所做的!它看到一个int和long,并决定该表达式应求值为Long。它将两个值拆箱,并将int隐式转换为Long。最后,它将结果Long装箱,使其变为Long并将其放入变量中。
实际上long可以存储整数的值,但integer不能存储long的值(概念正在扩展),并且您将其存储在Object中,这就是为什么将其存储在Long中的原因。内部也使用装箱和拆箱
可能的编译器代码:
Long obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass()+" nvalue =" + obj);
无效的代码(无法编译):
Integer obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass()+" nvalue =" + obj);
自己检查一下,让我知道是否有任何疑问。
1765

被折叠的 条评论
为什么被折叠?



