[toc]
Java版本从8到21的主要新特性 
Java作为最流行的编程语言之一,不断演进以适应现代软件开发需求。
下面总结了从Java 8到Java 21的主要新特性,如下表所示。
| Java版本 | 年份 | 主要新特性 | 
|---|---|---|
| Java 8 | 2014 | Lambda表达式、函数式接口、Stream API、接口默认方法、方法引用、Optional类、新的日期时间API等 | 
| Java 9 | 2017 | 模块系统、接口私有方法、集合工厂方法、JShell、响应式流、HTTP/2客户端(孵化)等 | 
| Java 10 | 2018 | 局部变量类型推断(var关键字)、应用类数据共享、并行全GC(G1)等 | 
| Java 11 | 2018 | HTTP客户端(标准)、字符串增强方法、单文件运行、var在Lambda中、Flight Recorder开源 | 
| Java 12 | 2019 | Switch表达式(预览)、JVM常量API、Shenandoah GC(实验)等 | 
| Java 13 | 2019 | 文本块(预览)、增强Switch表达式、动态CDS归档等 | 
| Java 14 | 2020 | instanceof模式匹配(预览)、Records(预览)、有用的NPE信息、Switch表达式(正式)等 | 
| Java 15 | 2020 | 文本块(正式)、Sealed类(预览)、隐藏类、ZGC正式 | 
| Java 16 | 2021 | Records(正式)、模式匹配instanceof(正式)、Stream.toList()、Vector API(孵化) | 
| Java 17 | 2021 | Sealed类(正式)、Switch模式匹配(预览)、移除Applet API | 
| Java 18 | 2022 | UTF-8默认字符集、简单Web服务器、Javadoc代码片段(@snippet) | 
| Java 19 | 2022 | 虚拟线程(预览)、Record模式(预览)、结构化并发(孵化)、外部函数API(预览) | 
| Java 20 | 2023 | 虚拟线程(第二次预览)、Scoped Values(孵化)、Record模式(第二次预览) | 
| Java 21 | 2023 | 虚拟线程(正式)、字符串模板(预览)、分代ZGC、Record模式(正式)、Switch模式匹配(正式) | 
Java 8 新特性 
Java 8是一个里程碑版本,引入了函数式编程范式,大大简化了代码编写。
java
// Lambda表达式 - 简化匿名内部类的编写
Runnable r = () -> System.out.println("Hello Lambda");
// Stream API - 提供函数式风格的数据处理
List list = List.of("apple", "banana", "cherry");
list.stream()
    .filter(s -> s.startsWith("a")) // 过滤出以a开头的元素
    .forEach(System.out::println);  // 方法引用,打印结果
// 接口默认方法 - 允许接口添加默认实现而不破坏兼容性
interface MyInterface {
    default void log() {
        System.out.println("Default method in interface");
    }
}
// Optional类 - 有效避免空指针异常
Optional optional = Optional.ofNullable(null);
optional.ifPresentOrElse(
    System.out::println, 
    () -> System.out.println("Value is empty")
);
// 新的日期时间API - 不可变、线程安全的日期时间处理
LocalDateTime now = LocalDateTime.now();
System.out.println("Current time: " + now);
// 日期计算
LocalDate tomorrow = now.plusDays(1).toLocalDate();
System.out.println("Tomorrow: " + tomorrow);Java 9 新特性 
Java 9引入了模块系统,增强了代码的封装性和可维护性。
java
// 模块系统 - 定义模块依赖关系
// module-info.java
module com.example {
    requires java.base; // 依赖基础模块
    exports com.example.api; // 导出公共API包
}
// 接口私有方法 - 允许接口中定义私有辅助方法
interface MyInterface {
    private void helper() {
        System.out.println("Private helper method");
    }
    
    default void publicMethod() {
        helper(); // 调用私有方法
        System.out.println("Public default method");
    }
}
// 集合工厂方法 - 创建不可变集合的简洁方式
List immutableList = List.of("a", "b", "c");
Set immutableSet = Set.of("x", "y", "z");
Map immutableMap = Map.of("one", 1, "two", 2);
// JShell - Java的交互式编程工具
// jshell命令行中执行
// jshell> System.out.println("Hello JShell");
// Hello JShell
// HTTP/2客户端(孵化)
HttpClient client = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2)
    .build();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://www.example.com"))
    .GET()
    .build();
// 同步发送请求
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Response status: " + response.statusCode());
System.out.println("Response body: " + response.body());Java 10 新特性 
Java 10引入了局部变量类型推断,简化了代码编写。
java
// 局部变量类型推断(var关键字)- 编译器自动推断变量类型
var list = List.of("a", "b", "c"); // 推断为List
var map = new HashMap(); // 推断为HashMap
// 应用类数据共享 - 提高JVM启动性能
// 启动参数: -XX:+UseAppCDS -Xshare:dump
// 这会创建共享归档文件,后续启动可使用: -XX:+UseAppCDS -Xshare:on
// 并行全GC(G1)- 提高垃圾收集效率
// 启动参数: -XX:+UseG1GC -XX:+ParallelRefProcEnabledJava 11 新特性 
Java 11是一个长期支持(LTS)版本,增加了许多实用功能。
java
// HTTP客户端(标准)- 正式版的HTTP客户端
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://www.example.com"))
    .timeout(Duration.ofSeconds(30))
    .build();
// 异步发送请求
CompletableFuture<HttpResponse> future = 
    client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
future.thenAccept(response -> {
    System.out.println("Async response: " + response.body());
});
// 字符串增强方法
String str = "   Hello, World!   \n";
System.out.println(str.isBlank()); // false - 判断是否为空或只包含空白字符
System.out.println("\n\t\n".isBlank()); // true
System.out.println(str.strip()); // "Hello, World!" - 去除首尾空白字符
System.out.println(str.stripTrailing()); // "   Hello, World!" - 去除尾部空白
System.out.println(str.stripLeading()); // "Hello, World!   \n" - 去除首部空白
System.out.println(str.repeat(2)); // 重复字符串两次
// 单文件运行 - 直接运行Java源文件而无需编译
// 命令行: java HelloWorld.java
// var在Lambda表达式中 - Lambda参数可以使用var
List names = List.of("Alice", "Bob", "Charlie");
names.forEach((var name) -> System.out.println("Hello, " + name));
// Flight Recorder开源 - 低开销的性能监控工具
// 启动参数: -XX:StartFlightRecording:filename=recording.jfrJava 12 新特性 
Java 12引入了Switch表达式预览,使switch语句更加灵活。
java
// Switch表达式(预览)- 箭头语法和直接返回值
int day = 1;
String dayName = switch (day) {
    case 1 -> "Monday";
    case 2 -> "Tuesday";
    case 3 -> "Wednesday";
    case 4 -> "Thursday";
    case 5 -> "Friday";
    case 6, 7 -> "Weekend";
    default -> "Unknown day";
};
System.out.println("Day: " + dayName); // "Day: Monday"
// JVM常量API - 提供对常量池常量的标准访问
java.lang.constant.Constable constable = "test";
Optional desc = constable.describeConstable();
// Shenandoah GC(实验)- 低延迟垃圾收集器
// 启动参数: -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGCJava 13 新特性 
Java 13增强了文本处理能力,引入了文本块预览功能。
java
// 文本块(预览)- 多行字符串字面量,可以保留格式
String html =   """
                123
                Hello, World!
                123
                """;
System.out.println(html);
// 增强Switch表达式 - 引入yield关键字返回值
int result = switch (day) {
    case 1: yield 10;
    case 2: yield 20;
    default: yield 0;
};
// 动态CDS归档 - 提高应用启动性能
// 启动参数: -XX:ArchiveClassesAtExit=app.jsa -XX:+UseAppCDSJava 14 新特性 
Java 14引入了模式匹配预览和Record类预览,简化了数据类的编写。
java
// instanceof模式匹配(预览)- 简化类型检查和转换
Object obj = "Hello Pattern Matching";
if (obj instanceof String str) {
    // 无需额外转换,直接使用str
    System.out.println("String length: " + str.length());
}
// Records(预览)- 不可变数据类的简洁表示
record Point(int x, int y) {
    // 可以添加静态方法
    public static Point origin() {
        return new Point(0, 0);
    }
    
    // 可以添加紧凑构造器(无需参数列表)
    public Point {
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException("Coordinates cannot be negative");
        }
    }
}
Point p = new Point(10, 20);
System.out.println("X: " + p.x() + ", Y: " + p.y());
// 有用的NPE信息 - 空指针异常提供更详细的错误信息
// 当执行以下代码时:
// String str = null;
// System.out.println(str.length());
// 异常信息会显示: java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
// Switch表达式(正式)- 正式版的Switch表达式
String season = switch (month) {
    case 12, 1, 2 -> "Winter";
    case 3, 4, 5 -> "Spring";
    case 6, 7, 8 -> "Summer";
    case 9, 10, 11 -> "Autumn";
    default -> "Unknown";
};Java 15 新特性 
Java 15将文本块正式化,并引入了密封类预览。
java
// 文本块(正式)- 多行字符串字面量正式版
String json = """
    {
        "name": "Java",
        "version": 15,
        "features": ["Text Blocks", "Sealed Classes"]
    }
""";
// 密封类(预览)- 限制类的继承关系
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;
    }
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}
public non-sealed class Rectangle extends Shape {
    private final double width;
    private final double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double area() {
        return width * height;
    }
}
// 隐藏类 - 用于动态生成和加载的类,提高性能
// 通过java.lang.invoke.MethodHandles.Lookup定义隐藏类
// ZGC正式 - 低延迟垃圾收集器正式版
// 启动参数: -XX:+UseZGCJava 16 新特性 
Java 16将Records和instanceof模式匹配正式化。
java
// Records(正式)- 不可变数据类正式版
record Person(String name, int age) {
    // 自动生成构造器、equals、hashCode和toString方法
}
Person person = new Person("Alice", 30);
System.out.println(person); // 输出: Person[name=Alice, age=30]
// 模式匹配instanceof(正式)- 类型检查和转换正式版
Object value = 42;
if (value instanceof Integer i && i > 10) {
    System.out.println("Greater than 10: " + i);
}
// Stream.toList() - 简化Stream转换为List的操作
List resultList = list.stream()
    .filter(s -> s.length() > 3)
    .toList(); // 返回不可变List
// Vector API(孵化)- 用于数学计算的向量操作
// 示例:向量加法
FloatVector va = FloatVector.fromArray(FloatVector.SPECIES_256, new float[]{1f, 2f, 3f, 4f}, 0);
FloatVector vb = FloatVector.fromArray(FloatVector.SPECIES_256, new float[]{5f, 6f, 7f, 8f}, 0);
FloatVector vc = va.add(vb);
float[] result = new float[4];
vc.intoArray(result, 0);
// result = [6.0, 8.0, 10.0, 12.0]
// 移除Deprecated的Applet APIJava 17 新特性 
Java 17是长期支持(LTS)版本,将Sealed类正式化。
java
// Sealed类(正式)- 限制类继承正式版
public sealed interface Operation 
    permits Add, Subtract, Multiply, Divide {}
public record Add(int a, int b) implements Operation {}
public record Subtract(int a, int b) implements Operation {}
public record Multiply(int a, int b) implements Operation {}
public record Divide(int a, int b) implements Operation {}
// Switch模式匹配(预览)- 模式匹配与switch结合
Object obj = new Person("Bob", 25);
String result = switch (obj) {
    case Person p -> "Person: " + p.name();
    case String s -> "String: " + s;
    case Integer i -> "Integer: " + i;
    default -> "Unknown type";
};
// 移除Applet API - 完全移除废弃的Applet相关类Java 18 新特性 
Java 18引入了UTF-8默认字符集和简单Web服务器。
java
// UTF-8默认字符集 - 所有平台上默认字符集变为UTF-8
// 无需再显式指定UTF-8字符集
InputStreamReader reader = new InputStreamReader(inputStream); // 默认使用UTF-8
// 简单Web服务器 - 用于测试和原型设计的轻量级服务器
// 命令行启动: jwebserver
// 或通过API启动
var server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/", exchange -> {
    String response = "Hello, World!";
    exchange.sendResponseHeaders(200, response.length());
    try (var os = exchange.getResponseBody()) {
        os.write(response.getBytes());
    }
});
server.start();
// Javadoc代码片段(@snippet)- 在文档中嵌入可编译的代码示例
/**
 * 计算两数之和
 * 示例用法:
 * {@snippet :
 * int sum = Calculator.add(5, 3);
 * System.out.println(sum); // 输出 8
 * }
 */
public static int add(int a, int b) {
    return a + b;
}Java 19 新特性 
Java 19引入了虚拟线程预览,为高并发应用提供了更高效的线程模型。
java
// 虚拟线程(预览)- 轻量级线程,显著提高并发性能
// 方式1: 直接启动虚拟线程
Thread.startVirtualThread(() -> {
    System.out.println("Running in virtual thread");
    try {
        Thread.sleep(Duration.ofSeconds(1));
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
});
// 方式2: 使用Executors
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    // 提交大量任务,自动使用虚拟线程
    for (int i = 0; i < 1000; i++) {
        final int taskId = i;
        executor.submit(() -> {
            System.out.println("Task " + taskId + " running");
            Thread.sleep(Duration.ofMillis(10));
            return taskId;
        });
    }
}
// Record模式(预览)- 模式匹配与Record结合
record Point(int x, int y) {}
Object obj = new Point(10, 20);
if (obj instanceof Point(int x, int y)) {
    System.out.println("X: " + x + ", Y: " + y);
    System.out.println("Distance from origin: " + Math.hypot(x, y));
}
// 结构化并发(孵化)- 简化并发编程,管理相关任务组
// 使用StructuredTaskScope
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Future future1 = scope.fork(() -> getFirstResult());
    Future future2 = scope.fork(() -> getSecondResult());
    
    scope.join(); // 等待所有任务完成
    scope.throwIfFailed(); // 如有任务失败,抛出异常
    
    // 获取结果
    String result1 = future1.resultNow();
    String result2 = future2.resultNow();
    
    System.out.println("Results: " + result1 + ", " + result2);
} catch (ExecutionException | InterruptedException e) {
    e.printStackTrace();
}
// 外部函数API(预览)- 与本地代码交互的标准方式
// 通过 Panama项目提供的API调用C函数Java 20 新特性 
Java 20对虚拟线程和Record模式进行了第二次预览,并引入了Scoped Values孵化功能。
java
// 虚拟线程(第二次预览)- 改进的虚拟线程实现
// 使用方式与Java 19相同,但有性能和功能改进
// Scoped Values(孵化)- 在线程间安全共享不可变数据
// 定义ScopedValue
static final ScopedValue USER = ScopedValue.newInstance();
// 设置并使用ScopedValue
ScopedValue.runWhere(USER, "admin", () -> {
    // 在这个作用域内,所有线程都可以访问USER的值
    System.out.println("Current user: " + USER.get());
    // 子任务也可以访问
    Thread.startVirtualThread(() -> {
        System.out.println("Virtual thread sees user: " + USER.get());
    });
});
// Record模式(第二次预览)- 增强的Record模式匹配
record Name(String first, String last) {}
record Person(Name name, int age) {}
Object obj = new Person(new Name("John", "Doe"), 30);
// 嵌套的Record模式
if (obj instanceof Person(Name(String first, String last), int age)) {
    System.out.println("Person: " + first + " " + last + ", Age: " + age);
}Java 21 新特性 
Java 21是目前最新的长期支持(LTS)版本,将虚拟线程和Record模式正式化。
java
// 字符串模板(预览)- 简化字符串拼接和格式化
String name = "Java";
int version = 21;
String message = STR."Hello \{name} \{version}!";
System.out.println(message); // 输出: "Hello Java 21!"
// 表达式中使用字符串模板
String json = STR."""
    {
        "name": "\{name}",
        "version": \{version},
        "features": ["Virtual Threads", "Record Patterns"]
    }
""";
// 虚拟线程(正式)- 轻量级线程正式版
// 使用方式与预览版相同,但已成为标准功能
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> {
        // 执行高并发任务
        System.out.println("Running in a virtual thread");
    });
}
// Record模式(正式)- Record模式匹配正式版
// 支持嵌套模式和类型模式
record Address(String street, String city, String country) {}
record Contact(String email, String phone) {}
record Customer(String id, Name name, Address address, Contact contact) {}
Object obj = new Customer("123", new Name("Jane", "Smith"), 
    new Address("123 Main St", "New York", "USA"),
    new Contact("jane@example.com", "555-1234"));
if (obj instanceof Customer(String id, Name(String first, String last), 
                          Address(String street, var city, _), 
                          Contact(var email, _))) {
    System.out.println("Customer " + first + " " + last + " (" + id + ")");
    System.out.println("Lives at " + street + ", " + city);
    System.out.println("Email: " + email);
}
// Switch模式匹配(正式)- 模式匹配与switch结合正式版
Object value = 42;
String formatted = switch (value) {
    case Integer i -> String.format("Integer: %d", i);
    case Long l -> String.format("Long: %d", l);
    case Double d -> String.format("Double: %.2f", d);
    case String s -> String.format("String: '%s'", s);
    default -> "Unknown type";
};
// 分代ZGC - 提高ZGC的吞吐量
// 启动参数: -XX:+UseZGC -XX:+ZGenerational