Java 代码对象o=true?新整数(0):新的Long(1)返回值为0的Long。为什么? 请考虑下面的代码: Object obj = true ? new Integer(0) : new Long(1); System.out.println(obj.getClass() + "\nvalue = " + obj);
其结果是:Java 代码对象o=true?新整数(0):新的Long(1)返回值为0的Long。为什么? 请考虑下面的代码: Object obj = true ? new Integer(0) : new Long(1); System.out.println(obj.getClass() + "\nvalue = " + obj);,java,Java,其结果是: class java.lang.Long value = 0 而不是: class java.lang.Integer value = 0 有人能解释一下为什么我们在Java中有这样的功能吗?这对我来说很奇怪。 你有什么例子可以说明这一点吗 更新: 这是一段字节码,我们可以看到,那里发生了什么 NEW java/lang/Integer DUP LDC "0" INVOKESPECIAL java/lang/Integer.<init> (Ljava/lang/Str
class java.lang.Long
value = 0
而不是:
class java.lang.Integer
value = 0
有人能解释一下为什么我们在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
newjava/lang/Integer
重复
最不发达国家“0”
调用特殊的java/lang/Integer。(Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/Integer.intValue()I
I2L
INVOKESTATIC java/lang/Long.valueOf(J)Ljava/lang/Long;
阿斯托尔1号
实际上,long可以存储整数的值,但integer不能存储long的值(概念正在扩展),您将其存储在Object中,这就是为什么它将其存储在long中。在内部,它也使用装箱和拆箱
可能的编译器代码:
Long obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass()+“\n值=”+obj)
不工作代码(无法编译):
System.out.println(obj.getClass()+“\n值=”+obj)
你自己检查一下,如果有任何疑问,请告诉我。这里发生的事情是由于
- 二进制数字提升将
和整数
类型转换为Long
,用作应用于条件运算符表达式的常用类型Long
- 取消包装那些包装器对象
- 然后装箱条件表达式的结果值
长
当然不是同一类型
但是,如中所述,编译器将在确定应用于表达式的可能公共类型时应用。该部分有一个方便的表15.25-D,它告诉我们,当第二个操作数的类型为Integer
,第三个操作数的类型为Long
,编译器将对Integer,Long
进行二进制数字升级。对整数、长
进行二进制数字升级将产生长
。因此,条件运算符表达式的结果是long
由于表达式的结果类型是long
,因此必须取消对Integer
或long
的装箱(如果是Integer
,则必须进行强制转换)
最后,将其指定给一个对象
,该对象强制装箱,并将长
包装为长
。因此,您将得到一个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);
表示取消对(long)(新整数(0)).intValue()
整数的装箱,并将其强制转换为
,以便与表达式结果类型匹配long
表示取消对(新的Long(1)).longValue()
的装箱,因此它与表达式结果类型匹配Long
- 而
表示最后的装箱Long.valueOf
:
出现在第二个和第三个表达式之间
[……]
条件表达式的类型确定如下:
- [……]
- 否则,如果第二个和第三个操作数的类型可转换为()数字类型,则有几种情况:
- [……]
- 否则,二进制数字提升()将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型
这与三元运算符的工作方式有关
:
两侧的操作数必须是兼容类型,因此您不能有以下操作数:
true ? 1 : "Hello"
因为int
和String
不能相互隐式转换
但是,在您的情况下,这些类型是兼容的!
int
可以隐式转换为long
。编译器就是这么做的!它看到一个int和一个long,并决定表达式的计算结果应为long
。它取消两个值的绑定,并隐式地将int
转换为long
。最后,它将结果long
装箱,使其变为long
,并将其放入变量中。要使三元语句有效,双方应返回相同的值type@PeterLawreyobjecto=false?新长(0):新整数(1)
还将返回类java.lang.Long
和1
。这不是最后一个论点的类型,而是一种可以通过扩大范围来接受的类型。我喜欢研究不好的问题得到很多赞成票。但如今,阅读JLS的要求太高了……澄清一下,这是另一本的复制品,而不是另一本。另请参阅并稍微相关
true ? 1 : "Hello"