JDK 8与JDK 10:三元/拆箱的区别

最近的Nicolai Parlog@nipafx鸣叫引起了我的注意,因为它引用了关于JDK 8JDK 10之间行为更改的有趣StackOverflow讨论 ,并询问“为什么?” SerCe 在StackOverflow线程上引用的问题最终归结为在JDK 8和JDK 10之间更改实现,正确实现 Java语言规范。

下面的代码清单(略有改编)改编自SerCe在StackOverflow线程上提供的原始示例。

在JDK 10和JDK 8中表现不同的改编示例

public static void demoSerCeExample()
{
   try
   {
      final Double doubleValue = false ? 1.0 : new HashMap<String, Double>().get("1");
      out.println("Double Value: " + doubleValue);
   }
   catch (Exception exception)
   {
      out.println("ERROR in 'demoSerCeExample': " + exception);
   }
}

使用JDK 8编译并执行上述代码后,它将生成如下输出:
Double Value: null
使用JDK 10编译并执行上述代码后,它将生成如下输出: ERROR in 'demoSerCeExample': java.lang.NullPointerException 在JDK 8中,三元运算符返回null以分配给局部变量doubleValue ,但在JDK 10中,为同一三元语句抛出NullPointerException

此示例的两个调整导致一些有趣的观察。 首先,如果将三元运算符中表示的文字常量1.0指定为Double.valueOf(1.0) ,则JDK 8和JDK 10都将局部变量设置为null而不是抛出NullPointerException 。 其次,如果使用基本类型double而不是引用类型Double声明了局部变量,则无论Java版本和是否使用Double.valueOf(double)都始终抛出NullPointerException 。 当然,第二个观察是有道理的,因为无论三元运算符如何处理对象或引用,都必须在某个点取消引用以将其分配给原始double类型,并且在示例中始终会导致NullPointerException

下表总结了这些观察结果:

完整的三元声明 设置局部变量doubleValue
JDK 8 JDK 10
Double doubleValue
= false
? 1.0
: new HashMap<String, Double>().get("1");
null NullPointerException
double doubleValue
   =  false
    ? 1.0
    : new HashMap<String, Double>().get("1");
NullPointerException NullPointerException
Double doubleValue
   =  false
    ? Double.valueOf(1.0)
    : new HashMap<String, Double>().get("1");
null null
double doubleValue
   =  false
    ? Double.valueOf(1.0)
    : new HashMap<String, Double>().get("1");
NullPointerException NullPointerException

对于这个一般的三进制示例,在两个Java版本中都避免NullPointerException的唯一方法是将局部变量声明为引用类型Double (无需取消装箱)并使用Double.valueOf(double)以便在整个引用过程中使用Double三元而不是原始的double 。 如果仅通过指定1.0隐含原始double ,则Java Map返回的Double在JDK 10中将被隐式取消装箱(取消引用),并导致异常。 根据Brian Goetz的说法 ,JDK 10使实现返回到符合规范的状态。

翻译自: https://www.javacodegeeks.com/2018/06/jdk-ternary-difference.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值