JDK 17 和JDK 8 相比增加了哪些新特性

JDK 17 新特性

JDK 17 和JDK 8 相比增加了哪些新特性



前言

JDK 17 是 Java 语言的一个重要版本,于 2021 年 9 月发布。它是自 JDK 11 以来的第二个长期支持(LTS)版本,具有多项重要的改进和新特性。


一、JDK17的新特性有哪些 ?

JDK 17相对于JDK 8增加了很多新特性,以下是一些主要的新特性:

  1. Sealed classes:允许限制类的继承和实现,有助于保证 API 类不被未授权的修改或扩展。

  2. Pattern matching for instanceof:允许在 switch
    语句中使用模式匹配来测试一个对象是否是某个类的实例,使得编写简洁易读的代码更加容易。

  3. Strong encapsulation of JDK internals:通过使外部代码无法访问 JDK 内部 API 来提高 JDK
    的安全性和可维护性。

  4. Foreign function and memory API:提供了与非 Java 代码和内存交互的标准API,使得与本地库和系统集成更加容易。

  5. Improved support for Unicode 13.0.0:包括对 Unicode 13.0.0
    中定义的新字符和属性的支持。

  6. Records:一种新的语言特性,用于定义轻量级、不可变的数据类,可以大大减少模板化代码的数量。

  7. Text blocks:允许在源代码中创建多行字符串,提高了代码的可读性。

  8. Switch expressions:允许在 switch 语句中使用表达式,而不仅仅是常量,使得编写简洁易读的代码更加容易。

除此之外,JDK 17还包括一些改进和优化,如:ZGC 改进,G1 改进,统一的 JVM 日志系统,可过滤的 JVM 日志,强化了java.net.URL 类的安全性等。

二、新特性Java代码演示

1.Sealed classes

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() 方法来计算它的面积。

2.Pattern matching for instanceof

首先定义一个 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 类型。


3 Records

首先定义一个 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。

4 Text blocks

使用 text blocks 可以更容易地创建包含多行文本的字符串。

例如,创建一个 HTML 页面:

String html = """
    <html>
        <body>
            <h1>Hello, world!</h1>
        </body>
    </html>
    """;

这里使用了三个双引号来定义多行文本字符串,使得代码更加易读。

5 Switch expressions

可以使用 switch 表达式,而不仅仅是常量,来更简洁地编写代码。

例如,计算一个整数的平方:

int num = 5;
int square = switch (num) {
    case 1, 2, 3 -> num;
    default -> num * num;
};
System.out.println(square);

这里使用了 switch 表达式,而不是 switch 语句,使得代码更加简洁。

6 Strong encapsulation of JDK internals

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 字段现在已经被标记为不再公开。

7 Foreign function and memory API

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 也提供了一种使用本地库和系统集成的标准方法。

8 Improved support for Unicode 13.0.0

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 方法来判断一个字符是否是表情符号,并根据结果输出相应的消息。

9 Vector API (preview)

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 中的一些新特性和改进,还有更多值得探索的特性和改进。

10 ZGC 改进

JDK 17 中对 ZGC(可伸缩的低延迟垃圾回收器)进行了一些改进,其中包括了针对 MappedByteBuffer 和堆外内存的改进,使得它们可以更快地进行垃圾回收,提高了应用程序的性能。

11 G1 改进

JDK 17 中对 G1(Garbage-First)垃圾回收器进行了一些改进,其中包括了针对大型堆的改进,以提高 G1 垃圾回收器的性能和可靠性。此外,还对 G1 进行了一些内存管理和优化,以提高垃圾回收的效率。

12 统一的 JVM 日志系统

JDK 17 中引入了一个统一的 JVM 日志系统,它可以在运行时收集并记录 JVM 和应用程序的日志信息,并支持按时间戳、等级和线程 ID 等进行筛选和过滤,以帮助开发人员更轻松地调试和分析应用程序的运行情况。

13 可过滤的 JVM 日志

JDK 17 中还增加了一些新的日志选项,使得开发人员可以更灵活地控制 JVM 的日志输出。其中包括了新的命令行选项和配置文件选项,以及一些用于控制日志输出格式和级别的 API。

14 强化了java.net.URL 类的安全性

JDK 17 中对 java.net.URL 类进行了一些改进,以增强其安全性。其中包括禁用了 java.net.URLClassLoader.newInstance(URL[]) 方法,以及限制了 java.net.URL 的默认协议处理器,以避免一些潜在的安全问题。此外,还提供了一些新的选项和 API,以帮助开发人员更好地控制和管理 java.net.URL 的使用。

总结

以上便是目前收集到的一些JDK17的一些新特性,希望对您能够提供帮助。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值