JDK14: JDK14新功能深度解析

it2024-04-21  4

在此次JDK14中,共更新了16个特性,下面对其中的六个主要的新特性做介绍。JDK14官方说明

主要七大特性

一.模式匹配instanceof(预览特性):

使用 instanceof,省去了在内部的类型转换,如下代码。

//新特性之前 @Test public void test1(){ Object obj=new String("hello,before JavaJdk14"); if (obj instanceof String){ String str =(String)obj; //必须显示的声明强制类型转换 System.out.println(str.contains(("Java"))); }else { System.out.println("非String类型"); } } //使用新特性 @Test public void test2(){ Object obj=new String("hello,JavaJdk15"); if (obj instanceof String str){ //新特性,省去了强制类型转换的过程 System.out.println(str.contains(("Java"))); }else { System.out.println("非String类型"); } }
二.实用的NullPointerException:

功能:在之前的JDK版本中出现空指针异常只会报错误,在JDK14中优化了这部分,将空指针具体出现地方表现出来。

NullPointerExceptionTest类

public class NullPointerExceptionTest { public static void main(String[] args) { String test=null; test.equals("abc"); } }

JDK14前出现的异常方式

Exception in thread "main" java.lang.NullPointerException at NullPointerExceptionTest.main(NullPointerExceptionTest.java:8)

JDK14后出现的异常方式

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "test" is null at NullPointerExceptionTest.main(NullPointerExceptionTest.java:8)

需要注意的是,此功能在JDK14中要配置参数 -XX:+ShowCodeDetailsInExceptionMessages进行开启,具体配置如下,在JDK15中默认启用,不用配置参数。

三.Record(预览特性):

功能:Record的使用与lombok插件的功能类似。当使用record关键字做如下声明时,解压下来的字节码如下所示。自动添加了构造函数,equals,toString等方法和变量。 Customer类

public record Customer(String name,String address) { }

Customer类的字节码文件

public final class Customer extends java.lang.Record { private final java.lang.String name; private final java.lang.String address; public Customer(java.lang.String name, java.lang.String address) { /* compiled code */ } public final java.lang.String toString() { /* compiled code */ } public final int hashCode() { /* compiled code */ } public final boolean equals(java.lang.Object o) { /* compiled code */ } public java.lang.String name() { /* compiled code */ } public java.lang.String address() { /* compiled code */ } }

Record还有其他功能如下

public record Customer(String name,String address) { //还可以声明构造器,静态变量,静态方法,实例方法 public Customer(String name){ this(name,null); } public static String info; public static void show(){ System.out.println("显示"); } public void showName(){ System.out.println("显示名字"); } //不可以在Record在定义实例变量 // public int id; } //Record不可以声明为abstract的 //abstract record User(){} //Record不可以显示的继承与其他类 //record User() extends Thread{}
四.表达式switch:

switch新特性在JDK12和JDK13已经两次进行预览,JDK14中确定使用,使用lamda表达式进行替换。

public class SwitchTest { @Test public void test1(){ Week day=Week.FRIDAY; switch (day){ case MONDAY: case TUESDAY: case WEDNESDAY: System.out.println("星期一或星期二或星期三"); case THURSDAY: case FRIDAY: System.out.println("星期四或星期五"); case SATURDAY: System.out.println("星期六"); case SUNDAY: System.out.println("星期日"); default: throw new IllegalStateException("What day is it today"+day); } } //jdk12新特性 public void test2(){ Week day=Week.FRIDAY; switch (day){ case MONDAY,TUESDAY,WEDNESDAY->System.out.println("星期一或星期二或星期三"); case THURSDAY,FRIDAY->System.out.println("星期四或星期五"); case SATURDAY->System.out.println("星期六"); case SUNDAY->System.out.println("星期日"); default ->throw new IllegalStateException("What day is it today"+day); } String result=switch (day){ case MONDAY,TUESDAY,WEDNESDAY->"星期一或星期二或星期三"; case THURSDAY,FRIDAY->"星期四或星期五"; case SATURDAY->"星期六"; case SUNDAY->"星期日"; default ->throw new IllegalStateException("What day is it today"+day); }; System.out.println(result); } //jdk13新特性 @Test public void text3(){ String text="5"; int num=switch (text){ case "1"->1; case "2"->2; case "3"->3; default -> { System.out.println("default"); yield 4; } }; System.out.println(num); } } enum Week{ MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY; }
五.TextBlocks(二次预览):

在JDK13进行第一次预览,在JDK14进行调整做二次预览。 用法:原来使用\n和字符串拼接对文本进行操作。在JDK13后,只要在文本前后添加""",文本会自动按照排列好的顺序进行换行,如下代码所示。

有个小点需要注意,此时text1的长度为65,text2的长度为66,这是因为在result文本后多出了个空格,只要按照Let we see result""",这种写法,长度将相同。

@Test public void text1(){ String text1="This is a text blocks\n"+ "I will test this function\n"+ "Let we see result"; System.out.println(text1); //JDK13 String text2= """ This is a text blocks I will test this function Let we see result """; System.out.println(); System.out.println(text2); System.out.println(text1.length()); System.out.println(text2.length()); } 前后添加""":表示自动按照排列好的文本进行生成添加\:表示取消换行操作添加\s:表示一个空格 @Test public void text2(){ String text1= """ This is a text blocks I will test this function Let we see result """; System.out.println(text1); //JDK14 // \:取消换行操作 // \s表示一个空格 String text2= """ This is a text blocks\ I will test this function\s Let we see result """; System.out.println(); System.out.println(text2); System.out.println(text1.length()); System.out.println(text2.length()); }
六.弃用ParallelScavenge + SerialOld GC组合:

官方解释:

There is one combination of GC algorithms that we believe is very little used but requires a significant amount of maintenance effort: The pairing of the parallel young generation GC (called ParallelScavenge) and the serial old GC (called SerialOld). This combination must be specifically enabled by the user with the -XX:+UseParallelGC -XX:-UseParallelOldGC command line options. 翻译:我们认为GC算法的组合很少使用,而且需要大量维护工作:并行年轻一代GC(称为ParallelScavenge)和串行老式GC(称为SerialOld)的配对。用户必须使用-XX:+ UseParallelGC -XX:-UseParallelOldGC命令行选项专门启用此组合。

This combination is unusual since it pairs the parallel young generation and serial old generation GC algorithms. We think this combination is only useful for deployments with a very large young generation and a very small old generation. In this scenario the full collection pause times might be bearable due to the small size of the old generation. In practice this is a very rare and risky deployment, since a slight shift in liveness for objects in the young generation will result in an OutOfMemoryException, since the old generation is significantly smaller than the young generation. The only advantage of this combination compared to using a parallel GC algorithm for both the young and old generations is slightly lower total memory usage. We believe that this small memory footprint advantage (at most ~3% of the Java heap size) is not enough to outweigh the costs of maintaining this GC combination. 翻译:这种组合是不寻常的,因为它将并行的年轻一代和串行的老一代GC算法配对在一起。我们认为这种组合仅对具有很大的年轻一代和很小的老一代的部署有用。在这种情况下,由于老一代的体积很小,因此可以接受整个收集的暂停时间。在实践中,这是非常罕见且危险的部署,因为年轻一代中对象的活动性略有变化将导致OutOfMemoryException,因为老一代的内存明显小于年轻一代。与针对年轻人和老年人使用并行GC算法相比,此组合的唯一优势是总内存使用量略低。我们认为,这种较小的内存占用优势(最多约为Java堆大小的3%)不足以超过维护此GC组合的成本。

七.删除CMS垃圾回收器:

CMS的弊端:

会产生内存碎片,导致并发清除后,用户线程可用的空间不足。CMS收集器对CPU的资源非常敏感。CMS收集器无法处理浮动垃圾。
最新回复(0)