当前位置: 首页 > 知识库问答 >
问题:

代码对象o=真?new Integer(0):new Long(1)返回值为0的Long。为什么?[副本]

东深
2023-03-14

请考虑我们有以下代码:

Object obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + 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.<init> (Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/Integer.intValue ()I
I2L
INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
ASTORE 1

共有2个答案

公孙俊弼
2023-03-14

这种行为在JLS-15.25中有很好的解释。条件运算符?·::

条件运算符有三个操作数表达式。出现在第一个和第二个表达式之间,而:出现在第二个和第三个表达式之间。

[...]

条件表达式的类型确定如下:

>

  • [...]

    否则,如果第二个和第三个操作数具有可转换为数值类型(§5.1.8)的类型,则有几种情况:

    >

  • [...]

    否则,对操作数类型应用二进制数字提升(§5.6.2),条件表达式的类型是第二个和第三个操作数的提升类型。

  • 公西俊德
    2023-03-14

    这里发生的事情是

    • 二进制数字提升,将整数类型转换为,用作应用于条件运算符表达式的通用类型
    • 取消包装对象的装箱
    • 然后装箱条件表达式的结果值

    条件运算符的第二个和第三个操作数必须具有相同的类型,这是表达式的结果类型。integerlong当然不是同一类型。

    但是,正如JLS§15.25中所描述的,编译器在确定应用于表达式的可能的通用类型时会应用二进制数值提升。该部分有一个方便的表15.25-D,它告诉我们,当第二个操作数的类型为integer而第三个操作数的类型为long时,编译器将对integer,long进行二进制数字提升。integer,long上的二进制数字提升生成long。因此条件运算符表达式的结果是long

    由于表达式的结果类型为long,因此必须将integerlong取消装箱(然后强制转换,对于integer)。

    最后,将其分配给一个对象,该对象强制装箱,并将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);
    
    • (long)(new Integer(0)).intValue()表示取消对Integer的装箱,并将其强制转换为long,以便与表达式结果类型匹配。
    • (新的Long(1)).longValue()表示取消对Long的装箱,以便与Expression结果类型匹配。
    • long.valueof表示结尾处的装箱。
     类似资料:
    • 查找表示整数为所需的最小位 为什么为值0返回0,难道不应该返回1吗。因为表示0所需的位数是1。 另外,我认为公式中的是一个偏移量

    • 我知道(-0==0)是真的。我很想知道为什么-0 当我在stackoverflow执行上下文中运行这段代码时,它返回。 但是当我在浏览器控制台中运行相同的代码时,它返回。那是为什么呢?我试图在谷歌上搜索它,但没有找到任何有用的东西。这个问题可能不会给某个人的实际例子增加价值,我想了解JS是如何计算它的。

    • 问题内容: 我有这样的事情: 而且我总是得到“时钟周期为:0-0”的输出 知道为什么会这样吗? (仅给出一点点细节,something_else()函数使用蒙哥马利表示法执行从左到右的求幂运算,而且我不确定不确定something_else()函数确实花费了一些不可忽略的时间。) 这是在Linux上。uname -a的结果是: 问题答案: 该功能不测量CPU时钟周期。 C说: “ 从实现定义的仅与

    • 问题内容: 为什么以下返回0? 问题答案: 月份从0(一月)到11(十二月)进行编号。 参考:

    • 我是一名高中生,目前正在为州学术会议(UIL)做准备。我有一个问题,我到处找,似乎找不到答案!为什么要打印0.0?

    • 问题内容: 在Python 2.6中查看Queue.py时,我发现这个结构有点奇怪: 如果maxsize为0,则队列永远不会满。 我的问题是在这种情况下如何运作?如何0 < 0 == 0被认为是错误的? 问题答案: 我相信Python对关系运算符的序列有特殊的处理方式,以使范围比较易于表达。能说比说好得多。 这些称为链接比较。这是他们文档的链接。 在您谈论的其他情况下,括号会强制在一个关系运算符之