JDK14特性
一、Java14概述
Oracle在2020年3月17日宣布JAVA14 全面上市,JAVA14通过每六个月发布一次新功能,为企业和开发人员社区提供增强功能,继续了Oracle加快创新的承诺. 最新的JAVA开发工具包提供了新功能,其中包括两项备受期待的新预览功能,实例匹配的匹配模式(JEP 305) 和记录(JEP 359),以及文本块的第二个预览(JEP 368),此外,最新的JAVA版本增加了对switch表达式的语言支持,公开了,用于持续监控JDK Flight Recorder数据的新API,将低延迟的Z垃圾收集器的可用性扩招到了macOS和Windows,并在孵化器模块中添加了包装完备的java应用程序和新的外部内存访问API,以安全高效的访问JAVA对外部的内存
可以在openjdk官网中观察到JDK14发布的jdk14详细官方计划和具体新特性详情
JAVA14 一共发行了16个JEP(JDK Enhancement Proposals,JDK 增强提案)
具体新增特性的介绍:
语言特性7项目:
- switch表达式(标准)
- 友好的空指针异常
- 非易失性字节缓冲区
- record
- instanceof模式匹配
- 文本块改进 二次预览
- 外部存储API
垃圾回收调整:
- G1的NUMA内存分配优化
新增工具:
- JAVA打包工具 孵化
- JFR事件流
增加废弃和移除:
- MacOS系统上的ZGC试验
- windows系统上的ZGC实验
- 弃用Parallel Scavenge 和Serial Old垃圾收集算法
- 弃用Solaris和SPCRC端口
- 移除CMS垃圾收集器
- 删除Pack200工具和API
二、语法层面的变化
1. instanceof
以往我们使用instanceof运算符都是先判断,然后在进行强转,例如我们查看String的equals方法源码.
public boolean equals(Object anObject) {if (this == anObject) {return true;}// 先进行类型的判断 if (anObject instanceof String) {// 然后进行强转String aString = (String)anObject;if (!COMPACT_STRINGS || this.coder == aString.coder) {return StringLatin1.equals(value, aString.value);}}return false;}
需要先判断类型然后强转,还要声明一个本地变量,语法比较麻烦。通常我们期望的是,在执行类型检测的同时执行类型转换
JEP305 新增了使instanceof运算符具有匹配的能力. 模式匹配能够是程序的通用逻辑更加简洁,代码更加简单,同时在做类型判断和类型转换的时候也更加安全.详情如下
JAVA14 提供了新的解决方案: 新的instanceof模式匹配,新的模式匹配语法是: 在instanceof的类型之后添加了变量. 如果对obj的类型检查通过,obj会被转换成后面的变量表示的数据类型. 数据类型的声明仅仅书写一次即可
Object obj ="hello java";
if(obj instanceof String str){System.out.println(str);}else{System.out.println("not a String");}
上述语法的判断逻辑时,如果obj是String类型,则会转换为后面的str,如果不是,则执行else
注意:
此时的str仅仅是if语句块里的局部变量,在else语句块中不可用
Object obj ="hello java";
// 这里做的是取反运算
if(!(obj instanceof String str) ){System.out.println("not a String");//System.out.println(str);// 这里不能使用str
}else{System.out.println(str);// 这里可以使用str
}
但是如果if语句中使用了! 这种取反运算,这个时候else才是相当于成功转换了,所以在else中可以使用str变量,if中则不能使用str变量。
Object obj =new Date();// "hello java";
if(obj instanceof String str && str.length()>2){System.out.println(str);
}else{System.out.println("not a String or length <=2");
}
上述语句块中,如果if中的判断逻辑比较复杂,是可以在后续的其他条件中使用str变量进行判断的,但是注意这里的运算符是短路与运算,就是要保证后面在使用str时,已经完成了转换,如果使用短路或运算,无法保证str是可以成功转换的,是不允许的,如下面的代码,就是错的
Object obj =new Date();// "hello java";
if(obj instanceof String str || str.length()>2){System.out.println(str);
}else{System.out.println("not a String or length <=2");
}
总之: if语句块中的小括号内,要保证成功的进行了转换才可以在if语句库中使用转换的对象,否则不可以
通过这个模式匹配,我们可以简化在类中重写的equals方法
import java.util.Objects;
class Person{private String pname;private Integer page;public Person(String pname,Integer page){this.pname =pname;this.page=page;}@Overridepublic boolean equals(Object obj){return obj instanceof Person p && Objects.equals(this.pname,p.pname)&& Objects.equels(this.page,p.page);}
}
2. switch表达式
java的Switch语句是一个一直在变化的语法,可能是因为之前的不够强大,在JAVA14中,我们依然可以看到对于switch的语法优化.
我们简单整理一下switch语句在各个版本中的特点
JAVA5 switch变量类型可以使用枚举了
JAVA7 switch变量类型中可以使用String
JAVA11 switch语句可以自动省略break导致的贯穿提示警告 case L ->
JAVA12 switch语句可以作为表达式,用变量接收结果,可以省略break
JAVA13 switch中可以使用yield关键字停止switch语句块
JAVA14 JEP361switch表达式(标准)是独立的,不依赖于JEP 325 和 JEP 354,也就是说这里开始,之前学习的switch语句的语法成为一个正式的标准.未来是否有更多的改进,我们可以拭目以待
JDK12对缺省break的贯穿弱点进行了改进,case: 改成 case L -> ,这样即使不写也不会贯穿了,而且可以作为表达式返回结果
var grade ="a";
var res =switch(grade){case "a" -> "优秀";case "b" -> "良好";case "c" -> "一般";case "d" -> "及格";default -> "no such grade";
}
JAVA12 开始也可以进行多值匹配的支持
var grade ="a";
var res =switch(grade){case "a","b" -> "优秀";case "c" -> "一般";case "d" -> "及格";default -> "no such grade";
}
JAVA13开始可以使用 yield返回结果,这里的case后面仍然是:
String x = "3";
int i =