最近的Nicolai Parlog ( @nipafx ) 鸣叫引起了我的注意,因为它引用了关于JDK 8和JDK 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

JDK 8与JDK 10:三元/拆箱的区别相关推荐

  1. jdk10与jdk9的区别_JDK 8与JDK 10:三元/拆箱的区别

    jdk10与jdk9的区别 最近的Nicolai Parlog ( @nipafx ) 鸣叫引起了我的注意,因为它引用了一个有趣的StackOverflow讨论 ,该讨论涉及JDK 8和JDK 10之 ...

  2. JDK 1.5 新特性——自动拆箱装箱

    1.5版本支持了自动包装和解包操作,对于bool/Boolean,byte/Byte,double/Double,short/Short,int/Integer, long/Long,float/Fl ...

  3. 可能你不知道的,关于自动装箱和自动拆箱

    包装类 我们知道,Java中包含了8种基本数据类型: 整数类型:byte.short.int.long 字符类型:char 浮点类型:float.double 布尔类型:boolean 这8种基本数据 ...

  4. 包装类-自动装箱和自动拆箱

    自动装箱:把基本数据类型转换为包装类型 自动拆箱:把包装类型转换成基本数据类型 public class Demo3 {public static void main(String[] args) { ...

  5. Java 基本类型与自动装箱、拆箱

    基本数据类型 基本类型,或者叫内置类型,是 Jav 中不同于类(class)的特殊类型.它们是我们编程中使用最频繁的类型. Java 是一种强类型语言,第一次申明必须说明数据类型,第一次变量赋值称为变 ...

  6. Java自动装箱/拆箱

    自动装箱和自动拆箱 那么Java中有八大基本数据类型,byte.char.short.int.long.double.float.boolean.而它们有对应的包装类 Byte.Character.S ...

  7. jdk 5 到 jdk 10各个版本的新特性

    jdk5 jdk10各个版本的新特性 JDK1.5新特性: 工程代号为Tiger(老虎) 自从JDK1.3开始,sun维持一个习惯,大约每隔两年发布一个JDK的主版本,以动物命名,期间发布的各个修正版 ...

  8. 2017.10.16 装箱和拆箱﹑火星车的升级

    装箱和拆箱(jdk1.5之后的新特性) 基本类型包装器 区别:基本类型重效率﹑包装器重功能 例: package com.dayuanit.test;public class TestLesson00 ...

  9. java三元表达式因自动拆箱导致的NPE问题

    开发中发生的奇怪的问题,类似如下的代码NPE了... boolean flag = false; Integer a = null; Integer n = flag ? 1 : a; 原来是在计算三 ...

最新文章

  1. JDOM是JAVA中最常用的一种解析XML的工具
  2. SpringCloud_Zuul
  3. 关于jquerymobile的预加载
  4. mongoose多个连接_连接(connections)
  5. 设置(TableViewController)通用框架
  6. Mercurial(Hg)基本操作
  7. linux arm 64 hard float abi,ARMHF(hard-float ABI for ARM)
  8. shell 执行失败重试_Smart Retry主要是用来进行方法重试
  9. keymap in ubuntu
  10. python的invalid syntax是什么意思_python中出现invalid syntax报错的几种原因
  11. 老男孩Linux架构师实战课程14期教程
  12. PCBA方案开发设计—咖啡秤厨房电子秤PCBA方案
  13. html代码中数学公式,html中使用mathjax数学公式
  14. 过渡矩阵、线性变换矩阵在对应基下坐标的求法
  15. 快速学习-web3.js简介与入门
  16. BIG-ENDIAN VS LITTLE-ENDIAN
  17. Android性能优化——启动优化简述
  18. 路由器把服务器的地址修改,路由器修改服务器地址
  19. AUTOCAD2020入门学习笔记(一)
  20. JMS RabbitMQ消息代理

热门文章

  1. 牛客国庆集训派对Day6
  2. 北方大学 ACM 多校训练赛 第十五场 蜘蛛牌A
  3. 节操大师 北方大学生程序设计竞赛 南开大学
  4. Java synchronized 中的while 和 notifyAll
  5. 推荐算法-关联分析(关联规则)
  6. Java5泛型的用法,T.class的获取和为擦拭法站台
  7. Spring Boot的自动化配置原理
  8. express中获取url参数
  9. Servlet 中文乱码处理
  10. js 方法传递对象参数