7. JDK14 新特性
参考网站: openjdk.org/projects/jd…
makefile复制代码
305:
Pattern Matching for instanceof (Preview)Instanceof 的模式匹配(预览)
343:
Packaging Tool (Incubator)包装工具(孵化器)
345:
NUMA-Aware Memory Allocation for G1基于 NUMA 的 G1内存分配
349:
JFR Event StreamingJFR 事件流
352:
Non-Volatile Mapped Byte Buffers非易失性映射字节缓冲区
358:
Helpful NullPointerExceptions有用的 NullPointerException
359:
Records (Preview)档案(预览)
361:
Switch Expressions (Standard)开关表达式(标准)
362:
Deprecate the Solaris and SPARC Ports废弃 Solaris 和 SPARC 端口
363:
Remove the Concurrent Mark Sweep (CMS) Garbage Collector删除并发标记扫描(CMS)垃圾收集器
364:
ZGC on macOS
365:
ZGC on WindowsWindows 上的 ZGC
366:
Deprecate the ParallelScavenge + SerialOld GC Combination不推荐使用并行清除 + SerialOld GC 组合
367:
Remove the Pack200 Tools and API删除 Pack200工具和 API
368:
Text Blocks (Second Preview)文本块(第二次预览)
370:
Foreign-Memory Access API (Incubator)外部内存访问 API (孵化器)
7.1 instanceof模式匹配
instanceof
模式匹配是JDK 14引入的一项新特性,用于简化对类型的检查和转换操作。在以往的Java版本中,使用instanceof
进行类型检查后,需要进行显式的类型转换才能使用该类型的特定方法或属性。而使用instanceof
模式匹配后,可以在同一表达式中进行类型检查和类型转换。 下面是一个使用instanceof
模式匹配的示例:
public void processShape(Shape shape) {
if (shape instanceof Circle c) {
double area = Math.PI * c.getRadius() * c.getRadius();
System.out.println("Circle area: " + area);
} else if (shape instanceof Rectangle r) {
double area = r.getWidth() * r.getHeight();
System.out.println("Rectangle area: " + area);
} else if (shape instanceof Triangle t) {
double area = 0.5 * t.getBase() * t.getHeight();
System.out.println("Triangle area: " + area);
} else {
System.out.println("Unknown shape");
}
}
在上述示例中,processShape
方法接收一个Shape
对象作为参数,并使用instanceof
模式匹配来检查对象的具体类型。如果对象是Circle
类型,则在if
语句中的instanceof
后声明一个新的变量c
,表示类型为Circle
的对象,然后可以直接使用c
的方法和属性。同样地,对于Rectangle
和Triangle
类型,也可以在对应的instanceof
语句中声明新的变量并使用。 这种模式匹配的语法形式为:instanceof 类型 变量
,其中类型
是要检查的类型,变量
是在该分支中表示该类型的对象。这样可以避免了显式的类型转换,使代码更加简洁和可读性更高。 需要注意的是,instanceof
模式匹配只在对应的if
语句分支中有效,如果想在后续的代码中继续使用已经声明的变量,需要将其提升到外部作用域。
7.2 Records(记录类型)
Records(记录类型)是JDK 14引入的一项新特性,它简化了创建不可变(immutable)数据对象的过程。通过使用record
关键字,可以定义一个记录类型,该类型自动生成了一些标准的方法,如构造函数、getter方法、equals()、hashCode()和toString()等方法。 以下是一个使用记录类型的示例:
public record Person(String name, int age) {
// 自动生成了构造函数和getter方法
}
// 创建记录类型的实例
Person person = new Person("John Doe", 30);
// 访问记录类型的属性
String name = person.name();
int age = person.age();
// 自动生成的toString()方法
System.out.println(person);
在上述示例中,使用record
关键字定义了一个名为Person
的记录类型,它有两个属性:name
和age
。通过定义记录类型,我们可以避免手动编写构造函数和getter方法,这些方法会自动生成并与记录类型绑定。 我们可以使用记录类型的构造函数来创建实例,然后通过自动生成的getter方法访问属性。例如,person.name()
返回记录类型实例的name
属性值。 此外,记录类型还提供了自动生成的equals()
和hashCode()
方法,用于比较记录类型的相等性和生成哈希码。同时,它还提供了自动生成的toString()
方法,用于以字符串形式表示记录类型的内容。 需要注意的是,记录类型是不可变的,即一旦创建,就不能修改其属性的值。如果需要修改属性,需要创建一个新的记录类型实例。 记录类型的引入简化了创建简单数据对象的过程,减少了样板代码,提高了代码的可读性和可维护性,尤其适用于那些只包含数据的简单对象。
7.3 Switch表达式扩展
JDK 14对switch表达式进行了扩展,使其更加强大和灵活。以下是一些switch表达式的扩展特性:
- 使用箭头语法(Arrow Syntax):在JDK 14之前,switch语句使用冒号(:)来分隔标签和相应的代码块。但在JDK 14中,引入了箭头(->)来替代冒号,使得switch语句更加简洁和易读。 示例:
int dayOfWeek = 3;
String dayType = switch (dayOfWeek) {
case 1, 2, 3, 4, 5 -> "Weekday";
case 6, 7 -> "Weekend";
default -> throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeek);
};
- 使用多个标签(Multiple Labels):在JDK 14中,可以在一个case语句中使用多个标签,以逗号分隔。这样可以将多个标签映射到同一段代码,避免了重复的代码块。 示例:
int number = 2;
switch (number) {
case 1, 2, 3:
System.out.println("Number is between 1 and 3");
break;
case 4, 5, 6:
System.out.println("Number is between 4 and 6");
break;
default:
System.out.println("Number is out of range");
break;
}
- 使用yield语句返回值(Yield Statement):在JDK 14中,可以在switch表达式的每个分支中使用yield语句返回一个值。这样可以更方便地从switch表达式中返回结果。 示例:
int number = 2;
String numberType = switch (number) {
case 0:
case 1:
yield "Even";
case 2:
case 3:
yield "Odd";
default:
yield "Unknown";
};
这些扩展使得switch表达式更加强大和灵活,能够更清晰地表达代码逻辑,并减少冗余代码。
7.4 垃圾回收器(Garbage Collectors)增强
在JDK 14中,引入了两个新的垃圾回收器:ZGC(Z Garbage Collector)和Shenandoah,以增强Java应用程序的垃圾回收性能。以下是对它们的简要介绍:
- ZGC(Z Garbage Collector):ZGC是一种低延迟的垃圾回收器,旨在减少Java应用程序的停顿时间。它是一种并发垃圾回收器,可以在非常短暂的暂停时间内执行大部分的垃圾回收操作。ZGC的目标是使得垃圾回收停顿时间不超过10毫秒,并且在几百兆字节至几个太字节的堆大小下具有可扩展性。
- Shenandoah:Shenandoah是另一种低延迟的垃圾回收器,专注于最小化应用程序的停顿时间。它是一种并发标记-清除垃圾回收器,它的主要目标是在堆大小为几百兆字节到几个太字节之间,提供可接受的垃圾回收停顿时间。Shenandoah采用了一种全局并发标记算法,使得标记阶段与应用程序线程并发执行,从而减少了停顿时间。
这两个垃圾回收器的共同目标是减少Java应用程序的停顿时间,以提高应用程序的响应性能。它们采用了不同的垃圾回收算法和技术,适用于不同的应用场景和堆大小。选择使用哪个垃圾回收器取决于应用程序的特性、性能需求以及硬件配置。 需要注意的是,ZGC和Shenandoah在JDK 14中被标记为实验性功能,可以通过命令行选项来启用它们。在后续的JDK版本中,这些垃圾回收器可能会继续改进和优化,以提供更好的性能和稳定性。
7.5 Numeral Formatting
在JDK 14中,引入了对Numeral Formatting的增强,主要通过java.text.NumberFormat
类的新方法和功能进行改进。以下是JDK 14中Numeral Formatting的一些新特性:
- 使用
CompactNumberFormat
类: JDK 14引入了CompactNumberFormat
类,它是NumberFormat
的子类,用于在格式化数字时以紧凑形式显示。它可以根据数字的大小自动选择合适的单位(如K、M、B等)来显示数字。 示例:
double value = 12345678;
NumberFormat nf = NumberFormat.getCompactNumberInstance();
String formattedValue = nf.format(value);
System.out.println(formattedValue); // 输出:12M
- 新的
toLocalizedPattern()
和toPattern()
方法: 在JDK 14中,NumberFormat
类新增了toLocalizedPattern()
和toPattern()
方法,用于获取数字格式化模式的本地化字符串表示和原始字符串表示。 示例:
NumberFormat nf = NumberFormat.getInstance();
String localizedPattern = nf.toLocalizedPattern();
String pattern = nf.toPattern();
System.out.println(localizedPattern);
System.out.println(pattern);
- 增强的小数位数控制: 在JDK 14中,
NumberFormat
类的setMaximumFractionDigits()
和setMinimumFractionDigits()
方法支持负数参数,用于设置小数位数的上限和下限。负数值表示保留尽可能多的小数位数,但至少保留指定的数目。 示例:
double value = 1234.56789;
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(-1); // 保留尽可能多的小数位数
nf.setMinimumFractionDigits(2); // 至少保留2位小数
String formattedValue = nf.format(value);
System.out.println(formattedValue); // 输出:1,234.56789
这些增强使得在JDK 14中进行Numeral Formatting更加方便和灵活。可以根据需求使用紧凑形式、获取格式化模式的本地化字符串表示以及对小数位数进行更精细的控制。