JDK 17 和JDK 8 相比增加了哪些新特性
JDK 17 是 Java 语言的一个重要版本,于 2021 年 9 月发布。它是自 JDK 11 以来的第二个长期支持(LTS)版本,具有多项重要的改进和新特性。
JDK 17相对于JDK 8增加了很多新特性,以下是一些主要的新特性:
Sealed classes:允许限制类的继承和实现,有助于保证 API 类不被未授权的修改或扩展。
Pattern matching for instanceof:允许在 switch
语句中使用模式匹配来测试一个对象是否是某个类的实例,使得编写简洁易读的代码更加容易。
Strong encapsulation of JDK internals:通过使外部代码无法访问 JDK 内部 API 来提高 JDK
的安全性和可维护性。
Foreign function and memory API:提供了与非 Java 代码和内存交互的标准API,使得与本地库和系统集成更加容易。
Improved support for Unicode 13.0.0:包括对 Unicode 13.0.0
中定义的新字符和属性的支持。
Records:一种新的语言特性,用于定义轻量级、不可变的数据类,可以大大减少模板化代码的数量。
Text blocks:允许在源代码中创建多行字符串,提高了代码的可读性。
Switch expressions:允许在 switch 语句中使用表达式,而不仅仅是常量,使得编写简洁易读的代码更加容易。
除此之外,JDK 17还包括一些改进和优化,如:ZGC 改进,G1 改进,统一的 JVM 日志系统,可过滤的 JVM 日志,强化了java.net.URL 类的安全性等。
JDK 17 引入了一种新的封闭类(sealed class)的概念。封闭类是一种限制继承的类,它只能被特定的子类继承。下面的代码演示了如何定义和使用封闭类:
代码如下:
public sealed class Shape permits Circle, Rectangle, Triangle {
public abstract double area();
}
public final class Circle extends Shape {
private final double radius;
public Circle(double radius) { this.radius = radius; }
public double area() { return Math.PI * radius * radius; }
}
public final class Rectangle extends Shape {
private final double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double area() { return width * height; }
}
public final class Triangle extends Shape {
private final double base, height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
public double area() { return 0.5 * base * height; }
}
public class ShapeExample {
public static void main(String[] args) {
Shape shape = new Circle(2.0);
System.out.println(shape.area());
}
}
// ...```
在这个例子中,我们定义了一个抽象的 Shape 类,并使用 permits 关键字限制它只能被 Circle、Rectangle 和 Triangle 这三个子类继承。然后,我们定义了这三个子类,并分别实现了它们的 area() 方法来计算它们的面积。最后,我们创建了一个 Circle 对象,并调用了它的 area() 方法来计算它的面积。
首先定义一个 Shape 接口:
public interface Shape {
double area();
}
//然后可以定义一个 Circle 类:
public class Circle implements Shape {
private final double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
接下来使用 instanceof 进行模式匹配:
Shape shape = new Circle(5.0);
if (shape instanceof Circle c) {
double radius = c.getRadius();
System.out.println("The area of the circle is: " + c.area());
}
这里使用了 instanceof 进行模式匹配,并将匹配到的对象强制转换为 Circle 类型。
首先定义一个 Record 类型:
public record Person(String name, int age) {
}
然后可以创建一个 Person 对象:
Person person = new Person("John Doe", 30);
System.out.println(person.name());
System.out.println(person.age());
这里使用了 record 关键字定义了一个记录类型,该类型包含两个属性:name 和 age。
使用 text blocks 可以更容易地创建包含多行文本的字符串。
例如,创建一个 HTML 页面:
String html = """
Hello, world!
""";
这里使用了三个双引号来定义多行文本字符串,使得代码更加易读。
可以使用 switch 表达式,而不仅仅是常量,来更简洁地编写代码。
例如,计算一个整数的平方:
int num = 5;
int square = switch (num) {
case 1, 2, 3 -> num;
default -> num * num;
};
System.out.println(square);
这里使用了 switch 表达式,而不是 switch 语句,使得代码更加简洁。
JDK 17 加强了对 JDK 内部 API 的封装,使得外部代码无法访问这些 API。例如,下面的代码演示了如何使用反射获取到 JDK 内部 API 的 Unsafe 类:
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class UnsafeExample {
public static void main(String[] args) throws Exception {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
System.out.println(unsafe);
}
}
然而,在 JDK 17 中,访问这个类的方式被阻止了。如果你尝试在 JDK 17 中运行上面的代码,你将会得到一个 java.lang.NoSuchFieldException: theUnsafe 异常,因为 theUnsafe 字段现在已经被标记为不再公开。
Foreign function and memory API 是一种与非 Java 代码和内存交互的标准 API。例如,以下代码演示了如何使用 Foreign Memory Access API 从 C 语言中分配内存:
import jdk.incubator.foreign.MemorySegment;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemoryLayout;
import jdk.incubator.foreign.MemoryAccess;
public class MemorySegmentExample {
public static void main(String[] args) {
try (MemorySegment segment = MemorySegment.allocateNative(1024)) {
MemoryAddress address = segment.baseAddress();
MemoryLayout layout = MemoryLayout.ofValue(1);
int value = 42;
MemoryAccess.setInt(address, 0, value);
int result = MemoryAccess.getInt(address, 0);
System.out.println(result);
}
}
}
这里使用了 Foreign Memory Access API 分配了 1024 字节的内存,然后将一个整数写入该内存并读取该整数,最后输出结果。
除此之外,Foreign Linker API 也提供了一种使用本地库和系统集成的标准方法。
JDK 17 提供了对 Unicode 13.0.0 中定义的新字符和属性的支持。例如,以下代码演示了如何使用 Character 类的新方法 isEmoji 判断一个字符是否是表情符号:
char emoji = 0x1F600;
if (Character.isEmoji(emoji)) {
System.out.println("This is an emoji!");
} else {
System.out.println("This is not an emoji.");
}
这里使用了 isEmoji 方法来判断一个字符是否是表情符号,并根据结果输出相应的消息。
Vector API 是 JDK 16 引入的一个预览特性,旨在提供一组用于高效处理向量(即多个数据元素)的 API,以利用现代硬件的 SIMD(Single Instruction Multiple Data)功能,提高 Java 应用程序的性能。
Vector API 的设计基于 Java 语言和 Java 虚拟机的现有基础,因此开发人员可以使用熟悉的 Java 语言和工具来编写和调试使用向量操作的代码,同时利用硬件的 SIMD 功能获得更高的性能。
Vector API 支持多种数据类型,包括整数、浮点数和布尔值,并提供了一组基本的向量操作,如加、减、乘、除等。此外,它还支持使用表达式的方式来描述向量操作,从而简化代码编写和优化过程。
需要注意的是,Vector API 目前仍处于预览状态,可能会在未来的版本中进行更改和调整。因此,在使用 Vector API 时,开发人员需要注意相应的限制和注意事项,并进行适当的测试和优化,以确保代码的正确性和性能。
import java.util.Arrays;
import jdk.incubator.vector.FloatVector;
import jdk.incubator.vector.VectorOperators;
public class VectorAdditionExample {
public static void main(String[] args) {
float[] a = {1.0f, 2.0f, 3.0f, 4.0f};
float[] b = {5.0f, 6.0f, 7.0f, 8.0f};
float[] result = new float[4];
// 使用 Vector API 进行向量加法
FloatVector va = FloatVector.fromArray(FloatVector.SPECIES_256, a, 0);
FloatVector vb = FloatVector.fromArray(FloatVector.SPECIES_256, b, 0);
FloatVector vc = va.add(vb);
// 将结果写入数组
vc.intoArray(result, 0);
// 输出结果
System.out.println(Arrays.toString(result));
}
}
该示例中,首先创建了两个长度为 4 的浮点数数组 a 和 b,并创建了一个用于存储结果的数组 result。然后,使用 FloatVector.fromArray 方法将数组转换为 FloatVector,并使用 add 方法执行向量加法操作。最后,使用 intoArray 方法将结果写入数组 result 中,并输出结果。
需要注意的是,上述示例中使用的是 SPECIES_256,它表示使用 AVX(Advanced Vector Extensions)指令集。Vector API 支持多种不同的指令集,包括 SSE、AVX、AVX-512 等。在实际使用中,开发人员应该根据具体的硬件和需求选择适当的指令集
这些只是 JDK 17 中的一些新特性和改进,还有更多值得探索的特性和改进。
JDK 17 中对 ZGC(可伸缩的低延迟垃圾回收器)进行了一些改进,其中包括了针对 MappedByteBuffer 和堆外内存的改进,使得它们可以更快地进行垃圾回收,提高了应用程序的性能。
JDK 17 中对 G1(Garbage-First)垃圾回收器进行了一些改进,其中包括了针对大型堆的改进,以提高 G1 垃圾回收器的性能和可靠性。此外,还对 G1 进行了一些内存管理和优化,以提高垃圾回收的效率。
JDK 17 中引入了一个统一的 JVM 日志系统,它可以在运行时收集并记录 JVM 和应用程序的日志信息,并支持按时间戳、等级和线程 ID 等进行筛选和过滤,以帮助开发人员更轻松地调试和分析应用程序的运行情况。
JDK 17 中还增加了一些新的日志选项,使得开发人员可以更灵活地控制 JVM 的日志输出。其中包括了新的命令行选项和配置文件选项,以及一些用于控制日志输出格式和级别的 API。
JDK 17 中对 java.net.URL 类进行了一些改进,以增强其安全性。其中包括禁用了 java.net.URLClassLoader.newInstance(URL[]) 方法,以及限制了 java.net.URL 的默认协议处理器,以避免一些潜在的安全问题。此外,还提供了一些新的选项和 API,以帮助开发人员更好地控制和管理 java.net.URL 的使用。
以上便是目前收集到的一些JDK17的一些新特性,希望对您能够提供帮助。