侧边栏壁纸
博主头像
ZHD的小窝博主等级

行动起来,活在当下

  • 累计撰写 79 篇文章
  • 累计创建 53 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

JDK 17 的新特性(LTS)

江南的风
2021-12-08 / 0 评论 / 0 点赞 / 25 阅读 / 14754 字 / 正在检测是否收录...

Java 17 的新特性

JDK 17 带来了多项新特性和改进,这些特性旨在提升Java语言的性能、易用性和安全性。以下是JDK 17的一些主要新特性:

JEP

描述

JEP 306

恢复始终严格的浮点语义

JEP 356

增强的伪随机数生成器

JEP 382

使用新的 macOS 渲染库

JEP 391

支持 macOS/AArch64 架构

JEP 398

删除已启用的 Applet API

JEP 403

更强的封装 JDK 内部封装

JEP 406

Switch 模式匹配(预览)

JEP 407

移除 RMI Activation

JEP 409

密封类(Sealed Classes)

JEP 410

移除实验性的 AOT 和 JIT 编译器

JEP 411

弃用 Security Manager

JEP 412

外部函数和内存 API(孵化器)

JEP 414

Vector API(第二孵化器)

JEP 415

指定上下文的反序列化过滤器

1. Switch表达式增强

  • 模式匹配:JDK 17中的switch表达式引入了模式匹配,包括类型模式和守卫模式。这允许在switch表达式中直接使用instanceof进行类型检查和转换,无需显式转换。

  • 语法简化:switch表达式中的case语句可以使用箭头(->)来直接返回结果,而无需使用break语句。同时,支持使用逗号分隔多个case标签,以便它们共享相同的代码块。

  • 对null值的支持:Switch表达式还允许我们直接处理null值,而无需在之前进行显式的null检查。

  • 例子

public void handleObject(Object obj) {  
    String result = switch (obj) {  
        case String s -> "处理字符串: " + s;  
        case Integer i -> "处理整数: " + i;  
        case List<?> list -> "处理列表";  
        case null -> "处理null值";  
        default -> "未知类型";  
    };  
    System.out.println(result);  
}  
  
// 使用示例  
public static void main(String[] args) {  
    HandleObjectDemo demo = new HandleObjectDemo();  
    demo.handleObject("Hello, JDK 17!");  
    demo.handleObject(123);  
    demo.handleObject(List.of("a", "b", "c"));  
    demo.handleObject(null);  
    demo.handleObject(new Object());  
}

2. 文本块(Text Blocks)

  • 多行字符串:文本块允许开发者以更自然、更易于阅读的方式编写多行字符串。它使用三个双引号(""")来定义字符串的开始和结束,并且支持在字符串内部包含换行符和缩进。

  • 转义字符:JDK 17对文本块进行了增强,提供了两个转义符(\ 和 \s\)用于将两行强制连接为一行或添加空白字符。

  • 例子

String html = """  
<html>  
    <body>  
        <h1>Hello, World!</h1>  
        <p>This is a text block example.</p>  
    </body>  
</html>  
""";  
System.out.println(html);

3. 伪随机数生成器(PRNG)

  • 增强型伪随机数生成器:JDK 17增加了伪随机数相关的类和接口,允许开发者使用stream流来操作随机数生成。这些新特性提供了更灵活、更强大的随机数生成能力。

  • 例子

import java.util.random.RandomGenerator;  
import java.util.random.RandomGeneratorFactory;  
  
public class RandomNumberDemo {  
    public static void main(String[] args) {  
        // 使用RandomGeneratorFactory获取一个RandomGenerator实例  
        // 这里以"L64X1024MixRandom"为例,它是一个具体的PRNG算法名称  
        RandomGeneratorFactory<RandomGenerator> factory = RandomGeneratorFactory.of("L64X1024MixRandom");  
        RandomGenerator rng = factory.create(System.currentTimeMillis()); // 使用当前时间作为种子  
  
        // 生成并打印一个随机整数  
        int randomNumber = rng.nextInt();  
        System.out.println("Random number: " + randomNumber);  
  
        // 生成并打印一系列指定范围内的随机整数  
        for (int i = 0; i < 10; i++) {  
            int randomInRange = rng.nextInt(10); // 生成0到9之间的随机整数  
            System.out.println(randomInRange);  
        }  
    }  
}

// PRNG算法
LXM:L32X64MixRandom
LXM:L128X128MixRandom
LXM:L64X128MixRandom
Legacy:SecureRandom
LXM:L128X1024MixRandom
LXM:L64X128StarStarRandom
Xoshiro:Xoshiro256PlusPlus
LXM:L64X256MixRandom
Legacy:Random
Xoroshiro:Xoroshiro128PlusPlus
LXM:L128X256MixRandom
Legacy:SplittableRandom
LXM:L64X1024MixRandom

4. 上下文特定的反序列化过滤器

Java序列化是核心功能,其重要性不言而喻,是Java在开发领域占据主导的关键之一。它简化了远程通信,并推动了Java EE的蓬勃发展。然而,Java序列化机制亦饱受诟病,其设计上的不足常导致诸多错误与维护难题。本质上,序列化概念无误,即将对象转换为跨JVM传输并可重建的格式,问题出在Java的实现上,频繁曝出安全漏洞。

反序列化风险高,因难以确保数据安全性,恶意数据流可能包含攻击代码,自由引用对象加剧了这一风险。

为此,JEP 415引入反序列化过滤机制,通过配置允许或禁止特定类的操作,有效遏制了潜在的安全威胁,确保被禁止的类在反序列化时失败,增强了系统的安全性。

例子:

  • 首先,我们需要定义一个可序列化的类:

import java.io.Serializable;  
  
public class User implements Serializable {  
    private static final long serialVersionUID = 1L;  
    private String name;  
    private int age;  
  
    // 构造函数、getter和setter省略  
  
    public User(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
  
    @Override  
    public String toString() {  
        return "User{" +  
                "name='" + name + '\'' +  
                ", age=" + age +  
                '}';  
    }  
}
  • 然后,我们编写一个主类来演示如何使用ObjectInputFilter来限制反序列化过程中可接受的类:

import java.io.*;  
  
public class SerializationDemo {  
  
    public static void main(String[] args) throws IOException, ClassNotFoundException {  
        // 序列化示例  
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);  
        User user = new User("Alice", 30);  
        objectOutputStream.writeObject(user);  
        objectOutputStream.close();  
  
        // 假设这是从网络或其他来源接收到的字节流  
        byte[] data = byteArrayOutputStream.toByteArray();  
  
        // 使用ObjectInputFilter来限制反序列化  
        ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(data)) {  
            {  
                // 只允许User类被反序列化  
                this.setObjectInputFilter(obj -> {  
                    if (obj instanceof Class && "User".equals(((Class<?>) obj).getSimpleName())) {  
                        return true;  
                    }  
                    return false;  
                });  
            }  
        };  
  
        try {  
            // 尝试反序列化  
            Object deserializedObject = objectInputStream.readObject();  
            System.out.println(deserializedObject);  
        } catch (InvalidClassException e) {  
            System.err.println("反序列化被拒绝,因为类不符合过滤器规则。");  
        }  
  
        objectInputStream.close();  
    }  
}

注意:上面的ObjectInputStream匿名子类示例是概念性的,用于说明如何可能实现一个过滤器。然而,在Java标准库中,ObjectInputStream并没有直接提供这样的构造函数或方法来设置过滤器。实际上,你需要使用ObjectInputFilter.Config来配置过滤器,但这通常是通过ObjectInputStream.setObjectInputFilter方法设置的,而该方法接受的是一个ObjectInputFilter实例,而不是在构造函数中设置。

由于Java API的限制,上面的代码示例需要稍作调整以符合实际使用方式。下面是一个更准确的示例,展示如何设置ObjectInputFilter

ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(data));  
  
// 定义一个简单的过滤器  
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(  
    "allowed.classes",  
    User.class.getName() // 只允许User类  
);  
  
objectInputStream.setObjectInputFilter(filter);
Object object = objectInputStream.readObject();
System.out.println(object.toString());

5. 密封类(Sealed Classes)

  • 控制继承:密封类允许类或接口的作者控制哪些类可以继承或实现它们。这通过关键字sealed、non-sealed和permits来实现,提供了比访问修饰符更具声明性的方式来限制超类的使用。

  • 安全性:密封类有助于创建更加安全和可维护的代码库,因为它限制了未经授权的类继承,减少了意外扩展的可能性。

6. 弃用和移除

  • Applet API:JDK 17弃用了Applet API,并计划在后续版本中移除。这反映了Applet技术在现代Web应用中的过时和不安全。

  • 安全管理器(Security Manager):JDK 17也弃用了安全管理器,并计划在后续版本中移除。安全管理器可追溯到Java 1.0,但多年来一直不是保护Java代码的主要手段。

7. 其他新特性

  • 恢复始终严格模式的浮点语义:修复了25年前英特尔浮点指令的一些问题,恢复了始终执行严格模式的浮点定义。

  • 新增macOS渲染管道:提供了对macOS平台的新渲染支持。

  • 支持将JDK移植到macOS或AArch64:增强了JDK的跨平台能力。

  • 强封装JDK内部API:提高了JDK内部API的封装性,减少了外部对内部实现的依赖。

  • 移除RMI(远程方法调用)激活机制:简化了RMI的使用和配置。

  • 外部函数和内存API(孵化器):允许Java程序与Java运行时之外的代码和数据进行互操作。

  • Vector API(第二孵化器):引入了一个API来表达向量计算,以实现优于等效标量计算的性能。

总的来说,JDK 17带来了多项重要的新特性和改进,这些特性旨在提升Java语言的性能、易用性和安全性。随着Spring Boot 3.0等框架对JDK 17的支持,越来越多的开发者将开始使用JDK 17来构建新的应用程序。

0

评论区