首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >三元运算符在JDK8和JDK10上的行为差异

三元运算符在JDK8和JDK10上的行为差异
EN

Stack Overflow用户
提问于 2018-06-09 08:29:15
回答 1查看 4.2K关注 0票数 59

考虑以下代码

代码语言:javascript
复制
public class JDK10Test {
    public static void main(String[] args) {
        Double d = false ? 1.0 : new HashMap<String, Double>().get("1");
        System.out.println(d);
    }
}

在JDK8上运行时,此代码将打印null,而在JDK10上,此代码将输出NullPointerException

代码语言:javascript
复制
Exception in thread "main" java.lang.NullPointerException
    at JDK10Test.main(JDK10Test.java:5)

除了JDK10编译器生成的两条额外的指令之外,编译器生成的字节码几乎是相同的,这两条指令与自动装箱相关,似乎是造成NPE的原因。

代码语言:javascript
复制
15: invokevirtual #7                  // Method java/lang/Double.doubleValue:()D
18: invokestatic  #8                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;

这种行为是JDK10中的错误,还是为了使行为更严格而有意做出的改变?

代码语言:javascript
复制
JDK8:  java version "1.8.0_172"
JDK10: java version "10.0.1" 2018-04-17
EN

回答 1

Stack Overflow用户

发布于 2018-06-09 09:09:49

JLS10似乎没有指定对条件运算符的任何更改,但我有一个理论。

根据JLS8和JLS10,如果第二个表达式(1.0)的类型为double,第三个表达式(new HashMap<String, Double>().get("1"))的类型为Double,则条件表达式的结果为double类型。Java8中的JVM似乎足够聪明,因为您将返回一个Double,所以没有理由首先将HashMap#get的结果解包为double,然后再将其装箱回Double (因为您指定了Double)。

为了证明这一点,在您的示例中将Double更改为double,然后抛出一个NullPointerException (在JDK8中);这是因为现在正在进行拆箱,而null.doubleValue()显然抛出了一个NullPointerException

代码语言:javascript
复制
double d = false ? 1.0 : new HashMap<String, Double>().get("1");
System.out.println(d); // Throws a NullPointerException

这似乎在10年中发生了变化,但我不能告诉你为什么。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50769880

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档