Java8之后的各个版本特性和代码示例

75 阅读15分钟

Java 8 (2014, LTS, ⭐⭐⭐⭐⭐)

  • Lambda 表达式:引入函数式编程范式,简化集合操作与并发编程。
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用 Lambda 表达式遍历集合
        names.forEach(name -> System.out.println("名字: " + name));

        // Lambda 实现 Runnable
        new Thread(() -> System.out.println("Lambda 线程运行中")).start();
    }
}
  • Stream API:提供声明式、链式集合操作,支持并行处理。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 过滤偶数并平方
        List<Integer> result = numbers.stream()
                                    .filter(n -> n % 2 == 0)
                                    .map(n -> n * n)
                                    .collect(Collectors.toList());
        System.out.println("偶数平方: " + result); // 输出: [4, 16]
    }
}
  • 接口默认方法:允许接口定义默认实现,增强接口扩展性。
// 定义带默认方法的接口
interface Greeting {
    void sayHello();

    // 默认方法
    default void sayBye() {
        System.out.println("再见!");
    }
}

// 实现接口
class EnglishGreeting implements Greeting {
    @Override
    public void sayHello() {
        System.out.println("Hello!");
    }
}

public class Main {
    public static void main(String[] args) {
        Greeting greeting = new EnglishGreeting();
        greeting.sayHello(); // 输出: Hello!
        greeting.sayBye();   // 输出: 再见!
    }
}
  • Optional 类:避免空指针异常,提升代码健壮性。
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        Optional<String> optional = Optional.ofNullable(null);

        // 安全获取值或默认值
        String value = optional.orElse("默认值");
        System.out.println("Optional 值: " + value); // 输出: 默认值

        // 使用 ifPresent 安全操作
        optional.ifPresent(v -> System.out.println("存在值: " + v)); // 不执行
    }
}
  • 方法引用:简化 Lambda 表达式写法。
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Java", "8", "方法引用");

        // 静态方法引用
        names.forEach(System.out::println);

        // 实例方法引用
        names.stream()
             .map(String::toUpperCase)
             .forEach(System.out::println);
    }
}
  • 新的日期/时间 API (java.time) :替代旧的 Date 和 Calendar,提供更清晰、线程安全的日期时间处理。
import java.time.*;

public class Main {
    public static void main(String[] args) {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        System.out.println("当前日期: " + today);

        // 计算一周后日期
        LocalDate nextWeek = today.plusWeeks(1);
        System.out.println("一周后: " + nextWeek);

        // 时间差计算
        LocalDateTime start = LocalDateTime.now();
        LocalDateTime end = start.plusHours(2);
        Duration duration = Duration.between(start, end);
        System.out.println("时间差: " + duration.toHours() + "小时"); // 输出: 2小时
    }
}

Java 9 (2017, ⭐⭐⭐⭐)

  • 模块化系统 (JPMS) :引入模块(Module),提升应用封装性和可维护性。
// 文件名:module-info.java
module com.example.hello {
    // 声明依赖的模块
    requires java.base;       // 隐式依赖,可省略
    requires java.net.http;   // 显式依赖 HTTP Client 模块

    // 导出包供其他模块使用
    exports com.example.hello.api;
}
  • JShell:交互式 REPL 工具,便于快速测试代码片段。
# 启动 JShell
$ jshell

# 在 JShell 中执行代码
jshell> int add(int a, int b) { return a + b; }
jshell> add(10, 20)
$1 ==> 30

# 退出 JShell
jshell> /exit
  • 集合工厂方法:简化不可变集合的创建(如 List.of())。
import java.util.List;
import java.util.Set;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        // 创建不可变 List
        List<String> list = List.of("Java", "9", "集合工厂");
        System.out.println(list);

        // 创建不可变 Set
        Set<Integer> set = Set.of(1, 2, 3);
        System.out.println(set);

        // 创建不可变 Map
        Map<String, Integer> map = Map.of("one", 1, "two", 2);
        System.out.println(map);
    }
}
  • 接口私有方法:允许接口定义私有方法,增强接口内部逻辑封装。
interface Calculator {
    // 默认方法
    default int add(int a, int b) {
        return sum(a, b);
    }

    // 私有方法(只能在接口内部使用)
    private int sum(int x, int y) {
        return x + y;
    }
}

public class Main implements Calculator {
    public static void main(String[] args) {
        Calculator calc = new Main();
        System.out.println("10 + 20 = " + calc.add(10, 20));
    }
}
  • HTTP/2 和 WebSocket API:内置支持现代网络协议。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        // 创建 HTTP 客户端
        HttpClient client = HttpClient.newHttpClient();

        // 构建 HTTP 请求
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://httpbin.org/get"))
                .GET()
                .build();

        // 发送请求并获取响应
        HttpResponse<String> response = client.send(
                request,
                HttpResponse.BodyHandlers.ofString()
        );

        // 输出响应状态码和正文
        System.out.println("状态码: " + response.statusCode());
        System.out.println("响应体: " + response.body());
    }
}
  • 多版本兼容 JAR
// 假设项目结构:
// src/main/java9/com/example/Version.java
// src/main/java8/com/example/Version.java

// Java 9 版本实现
package com.example;

public class Version {
    public static String get() {
        return "当前运行环境: Java 9";
    }
}

// 编译时指定版本输出目录:
// javac -d out/9 --release 9 src/main/java9/com/example/Version.java
// jar --create --file app.jar -C out/9 .
// 运行时自动加载对应版本类

Java 10 (2018, ⭐⭐⭐)

  • 局部变量类型推断 (var) :简化局部变量声明,提升代码可读性。
import java.util.*;

public class Main {
    public static void main(String[] args) {
        // 使用 var 声明局部变量,编译器自动推断类型
        var list = new ArrayList<String>(); // 推断为 ArrayList<String>
        list.add("Java 10");
        list.add("var 关键字");
        System.out.println("列表内容: " + list);

        // 在 for-each 循环中使用 var
        for (var item : list) {
            System.out.println("元素: " + item);
        }

        // 在 try-with-resources 中使用 var
        try (var stream = new java.io.ByteArrayInputStream("test".getBytes())) {
            System.out.println("可用字节数: " + stream.available());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • G1 并行 Full GC:优化垃圾回收性能,减少停顿时间。
  • 不可变集合的 copyOf 方法
import java.util.*;

public class Main {
    public static void main(String[] args) {
        // 创建可变集合
        List<String> mutableList = new ArrayList<>();
        mutableList.add("Java");
        mutableList.add("10");

        // 创建不可变副本
        var immutableList = List.copyOf(mutableList);
        System.out.println("不可变列表: " + immutableList);

        // 尝试修改会抛出 UnsupportedOperationException
        try {
            immutableList.add("新增元素");
        } catch (UnsupportedOperationException e) {
            System.out.println("不可变集合无法修改!");
        }
    }
}
  • Optional 的 orElseThrow() 方法
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        // 创建空 Optional
        Optional<String> emptyOpt = Optional.empty();

        // 使用 orElseThrow 在值为空时抛出异常
        try {
            var value = emptyOpt.orElseThrow(() -> new RuntimeException("值不存在"));
            System.out.println(value);
        } catch (RuntimeException e) {
            System.out.println("捕获异常: " + e.getMessage());
        }
    }
}

Java 11 (2018, LTS, ⭐⭐⭐⭐)

  • HTTP Client 正式版:标准化 HTTP/1.1 和 HTTP/2 客户端 API。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        // 创建 HTTP 客户端
        var client = HttpClient.newHttpClient();

        // 构建请求
        var request = HttpRequest.newBuilder()
                .uri(URI.create("https://httpbin.org/get"))
                .GET()
                .build();

        // 发送请求并获取响应
        var response = client.send(request, HttpResponse.BodyHandlers.ofString());

        // 输出状态码和响应体
        System.out.println("状态码: " + response.statusCode());
        System.out.println("响应体前50字符: " + response.body().substring(0, 50));
    }
}
  • 单文件运行:支持直接运行单文件 Java 程序(无需编译)。
// 保存为 Hello.java,直接运行:java Hello.java
public class Hello {
    public static void main(String[] args) {
        var message = "Hello from Java 11 单文件运行!";
        System.out.println(message);
    }
}
  • ZGC(实验) :低延迟垃圾收集器,适合大内存应用。
  • 字符串增强:新增 repeatstripisBlank 等方法。
public class Main {
    public static void main(String[] args) {
        var text = "  Java 11  ";

        // strip() - 去除首尾空白字符(Unicode标准)
        System.out.println("strip后: '" + text.strip() + "'");

        // isBlank() - 检查是否为空或仅含空白字符
        System.out.println("是否空白: " + text.isBlank());

        // repeat() - 重复字符串
        System.out.println("重复3次: " + "Hi ".repeat(3));

        // lines() - 按行分割流
        var multiline = "Line1\nLine2\nLine3";
        multiline.lines().forEach(line -> System.out.println("行: " + line));
    }
}
  • Optional 的 isEmpty() 方法
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        // 空 Optional
        var emptyOpt = Optional.<String>empty();
        System.out.println("是否为空: " + emptyOpt.isEmpty()); // true

        // 非空 Optional
        var presentOpt = Optional.of("Java 11");
        System.out.println("是否为空: " + presentOpt.isEmpty()); // false
    }
}

Java 12 (2019, ⭐⭐)

  • Switch 表达式(预览) :增强 switch 语句,支持返回值。
public class Main {
    public static void main(String[] args) {
        var day = 3;

        // Switch 表达式(预览):返回值 + 箭头语法
        var dayType = switch (day) {
            case 1, 2, 3, 4, 5 -> "工作日";
            case 6, 7           -> "周末";
            default             -> "未知";
        };
        System.out.println("第" + day + "天是:" + dayType); // 输出: 第3天是:工作日

        // Switch 表达式直接返回值
        var result = switch ("A") {
            case "A" -> 100;
            case "B" -> 200;
            default  -> 0;
        };
        System.out.println("结果: " + result); // 输出: 结果: 100
    }
}
  • Shenandoah GC(实验) :低暂停时间垃圾收集器。
  • 数字格式化工具类(NumberFormat 新增)
import java.text.NumberFormat;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // 紧凑数字格式化(如 1.2K, 3.4M)
        var formatter = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
        System.out.println("紧凑格式: " + formatter.format(1200));   // 输出: 1.2K
        System.out.println("紧凑格式: " + formatter.format(3400000)); // 输出: 3.4M
    }
}
  • 字符串缩进方法(indent
public class Main {
    public static void main(String[] args) {
        var text = "Java\n12\nindent";

        // 缩进 4 个空格
        var indented = text.indent(4);
        System.out.println(indented);
        // 输出:
        //     Java
        //     12
        //     indent

        // 负值缩进(去除空格)
        var dedented = "    Hello".indent(-2);
        System.out.println("'" + dedented + "'"); // 输出: '  Hello'
    }
}
  • Files.mismatch 方法(文件内容比较)
import java.nio.file.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // 创建临时文件
        var file1 = Files.createTempFile("test1", ".txt");
        var file2 = Files.createTempFile("test2", ".txt");

        // 写入不同内容
        Files.writeString(file1, "Java 12");
        Files.writeString(file2, "Java 11");

        // 比较文件差异位置(返回第一个不匹配的字节偏移量)
        long mismatchPos = Files.mismatch(file1, file2);
        System.out.println("首次不匹配位置: " + mismatchPos); // 输出: 5 (字符 '1' vs '2')

        // 清理临时文件
        Files.delete(file1);
        Files.delete(file2);
    }
}

Java 13 (2019, ⭐⭐)

  • 文本块(预览) :简化多行字符串书写(使用 """)。
public class Main {
    public static void main(String[] args) {
        // 文本块:使用"""定义多行字符串,自动处理换行和缩进
        var json = """
                   {
                       "name": "Java 13",
                       "feature": "Text Blocks",
                       "preview": true
                   }
                   """;
        System.out.println("生成的JSON:\n" + json);

        // 文本块保留末尾换行
        var sql = """
                  SELECT *
                  FROM users
                  WHERE id = ?
                  """;
        System.out.println("SQL查询:\n" + sql);
    }
}

Java 14 (2020, ⭐⭐⭐)

  • instanceof 模式匹配(预览) :简化类型检查和转换。
public class PatternMatchingExample {
    public static void main(String[] args) {
        Object obj = "Java 14";

        // 类型判断 + 变量声明合并(无需显式强转)
        if (obj instanceof String s) {
            System.out.println("字符串长度: " + s.length()); // 输出: 字符串长度: 7
        }
    }
}
  • Record 类(预览) :简化不可变数据类的定义。
// Record 自动生成构造器、getter、equals、hashCode、toString
public record Person(String name, int age) {}

public class RecordExample {
    public static void main(String[] args) {
        var person = new Person("张三", 30);
        System.out.println(person); // 输出: Person[name=张三, age=30]
    }
}
  • Switch 表达式(正式特性,JEP 361)
public class SwitchExample {
    public static void main(String[] args) {
        var day = "MONDAY";

        // Switch 表达式返回值(无需 break,支持 yield)
        var type = switch (day) {
            case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "工作日";
            case "SATURDAY", "SUNDAY" -> "周末";
            default -> throw new IllegalArgumentException("无效日期");
        };
        System.out.println(day + " 是:" + type); // 输出: MONDAY 是:工作日
    }
}
  • Helpful NullPointerExceptions(默认启用,JEP 358)
public class HelpfulNPEExample {
    public static void main(String[] args) {
        String nullString = null;

        try {
            // 触发 NPE,异常信息会包含具体变量名
            var length = nullString.length();
        } catch (NullPointerException e) {
            System.out.println("捕获 NPE: " + e.getMessage());
            // 输出示例: Cannot invoke "String.length()" because "nullString" is null
        }
    }
}

Java 15 (2020, ⭐⭐)

  • 文本块(正式) :正式发布多行字符串语法。
public class TextBlocks {
    public static void main(String[] args) {
        // 文本块:多行字符串,自动处理缩进和换行
        var json = """
                   {
                       "name": "Java 15",
                       "feature": "Text Blocks",
                       "status": "正式"
                   }
                   """;
        System.out.println("生成的 JSON:\n" + json);
    }
}
  • Sealed Classes(预览) :限制类的继承层次,增强类型安全。
// 文件名: SealedDemo.java
// 编译: javac --release 15 --enable-preview SealedDemo.java
// 运行: java --enable-preview SealedDemo

// 密封基类(必须放在最前面)
public abstract sealed class SealedDemo permits SealedDemo.Circle, SealedDemo.Square {
    // 抽象方法
    public abstract double area();

    // 允许的子类
    // 1. final 子类(终结继承链)
    public static final class Circle extends SealedDemo {
        private final double radius;

        public Circle(double radius) {
            this.radius = radius;
        }

        @Override
        public double area() {
            return Math.PI * radius * radius;
        }
    }

    // 2. non-sealed 子类(开放继承)
    public static non-sealed class Square extends SealedDemo {
        private final double side;

        public Square(double side) {
            this.side = side;
        }

        @Override
        public double area() {
            return side * side;
        }
    }

    // 测试方法(放在最后)
    public static void main(String[] args) {
        // 创建实例
        SealedDemo circle = new Circle(5.0);
        SealedDemo square = new Square(4.0);

        // 输出结果
        System.out.printf("圆形面积: %.2f%n", circle.area());   // 输出: 圆形面积: 78.54
        System.out.printf("正方形面积: %.2f%n", square.area()); // 输出: 正方形面积: 16.00
    }
}

Java 16 (2021, ⭐⭐⭐)

  • Record 类(正式) :正式发布不可变数据类。
// 文件名: RecordAndPattern.java
// 编译: javac --release 16 RecordAndPattern.java
// 运行: java RecordAndPattern

// 1. Java 16正式特性:record(自动生成构造器、getter、equals、hashCode、toString)
public record Person(String name, int age) {}

// 2. Java 16正式特性:instanceof模式匹配(直接声明变量并转换类型)
public class RecordAndPattern {
    public static void main(String[] args) {
        // 创建record实例
        var person = new Person("张三", 30);

        // instanceof模式匹配
        if (person instanceof Person p) {
            System.out.printf("姓名: %s, 年龄: %d%n", p.name(), p.age()); // 输出: 姓名: 张三, 年龄: 30
        }

        // record的自动方法
        System.out.println("record的toString(): " + person); // 输出: record的toString(): Person[name=张三, age=30]
        System.out.println("record的equals(): " + person.equals(new Person("张三", 30))); // 输出: record的equals(): true
    }
}
  • Stream.toList() :简化 Stream 转 List 操作。
import java.util.stream.*;

public class StreamToListDemo {
    public static void main(String[] args) {
        var stream = Stream.of("Java", "16", "Stream");

        // Java 10 方式(仍可用)
        var list1 = stream.collect(Collectors.toUnmodifiableList());

        // Java 16 简化方式
        var list2 = stream.toList(); // 等价于上面的写法

        System.out.println(list1); // 输出: [Java, 16, Stream]
        System.out.println(list2); // 输出: [Java, 16, Stream]
    }
}

Java 17 (2021, LTS, ⭐⭐⭐⭐)

  • Sealed Classes(正式) :正式发布密封类。
// 文件名: SealedClasses.java
// 编译: javac --release 17 SealedClasses.java
// 运行: java SealedClasses

// Java 17正式特性:密封类
public sealed class SealedClasses permits Circle, Square {
    public abstract double area();
}

// 允许的子类
final class Circle extends SealedClasses {
    private final double radius;
    public Circle(double radius) { this.radius = radius; }
    public double area() { return Math.PI * radius * radius; }
}

non-sealed class Square extends SealedClasses {
    private final double side;
    public Square(double side) { this.side = side; }
    public double area() { return side * side; }
}

// 测试类
class SealedTest {
    public static void main(String[] args) {
        SealedClasses circle = new Circle(5.0);
        SealedClasses square = new Square(4.0);
        
        System.out.printf("圆形面积: %.2f%n", circle.area());
        System.out.printf("正方形面积: %.2f%n", square.area());
    }
}
  • 模式匹配 Switch(预览) :增强 switch 语句的模式匹配能力。
// 文件名: PatternMatching.java
// 编译: javac --release 17 PatternMatching.java
// 运行: java PatternMatching

public class PatternMatching {
    public static void main(String[] a) {
        Object obj = "Hello, Java 17!";
        
        // switch模式匹配(自动类型转换)
        String result = switch (obj) {
            case String s -> "字符串: " + s;
            case Integer i -> "整数: " + i;
            default -> "其他类型";
        };
        System.out.println(result);
    }
}
  • 移除 Applet:彻底移除已废弃的 Applet 支持。

Java 18 (2022, ⭐)

  • 简单 Web 服务器 (jwebserver) :内置轻量级静态文件服务器。
// 文件名: SimpleWebServer.java
// 编译: javac --release 18 SimpleWebServer.java
// 运行: java SimpleWebServer

import com.sun.net.httpserver.*;
import java.net.*;
import java.nio.file.*;

public class SimpleWebServer {
    public static void main(String[] args) throws Exception {
        // 创建并启动简单文件服务器
        HttpServer server = SimpleFileServer.createFileServer(
            new InetSocketAddress(8000), 
            Paths.get("."), 
            SimpleFileServer.OutputLevel.VERBOSE
        );
        server.start();
        System.out.println("服务器已启动:http://localhost:8000");
    }
}
  • 默认 UTF-8:统一默认字符编码为 UTF-8,解决乱码问题。

Java 19 (2022, ⭐⭐⭐⭐)

  • 虚拟线程(预览) :轻量级线程模型,支持高并发。
// 文件名:VirtualThreadDemo.java
// 运行:java --enable-preview  VirtualThreadDemo.java

import java.util.concurrent.*;

public class VirtualThreadDemo {
    public static void main(String[]  args) {
        // 使用虚拟线程
        ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();

        // 创建并启动虚拟线程
    }
  • 结构化并发(预览) :简化多线程错误处理和取消操作。
// 文件名: StructuredConcurrency.java
// 编译: javac --release 18 StructuredConcurrency.java
// 运行: java StructuredConcurrency

import java.util.concurrent.*;
import java.time.*;

public class StructuredConcurrency {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            // 启动两个并发任务
            Future<String> task1 = scope.fork(() -> {
                Thread.sleep(1000);
                return "任务1结果";
            });
            
            Future<String> 任务2 = scope.fork(() -> {
                Thread.sleep(2000);
                return "任务2结果";
            });
            
            // 等待所有任务完成
            scope.join();
            scope.throwIfFailed(); // 如果有异常会在这里抛出
            
            // 获取结果
            System.out.println("任务1: " + task1.resultNow());
            System.out.println("任务2: " + 任务2.resultNow());
        }
    }
}

Java 20 (2023, ⭐⭐)

  • Scoped Values(预览) :线程局部变量的改进,支持作用域值传递。允许在同一线程或跨线程安全地共享不可变数据,比 ThreadLocal 更轻量、更适合虚拟线程。
// 定义一个作用域值
final static ScopedValue<String> USER = ScopedValue.newInstance();

public static void main(String[] args) {
    // 在当前作用域内绑定值并执行
    ScopedValue.where(USER, "Alice")
               .run(() -> {
                   System.out.println("当前用户: " + USER.get()); // 输出: 当前用户: Alice
                   callAnotherMethod();
               });
}

static void callAnotherMethod() {
    // 子方法中也能直接访问
    System.out.println("在子方法中用户: " + USER.get()); // 输出: 在子方法中用户: Alice
}
  • Record 模式匹配(预览) :增强模式匹配对 Record 的支持。对 record 类型进行模式匹配,可直接解构字段。
record Point(int x, int y) {}

public static void main(String[] args) {
    Object obj = new Point(10, 20);

    // 使用 record pattern 进行模式匹配
    if (obj instanceof Point(var x, var y)) {
        System.out.printf("坐标: (%d, %d)%n", x, y); // 输出: 坐标: (10, 20)
    }
}
  • switch 模式匹配:在 switch 语句中直接进行类型判断并绑定变量,代码更简洁。
static String formatter(Object o) {
    return switch (o) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %f", d);
        case String s  -> String.format("String %s", s);
        default        -> o.toString();
    };
}

public static void main(String[] args) {
    System.out.println(formatter(42));      // 输出: int 42
    System.out.println(formatter("hello")); // 输出: String hello
}
  • 外部函数与内存 API:提供与本地代码(C/C++)互操作的标准 API,替代 JNI。
// 假设已加载本地库 "libmath"
import jdk.incubator.foreign.*;

public class NativeMath {
    // 声明本地函数
    private static final SymbolLookup MATH = SymbolLookup.loaderLookup();
    private static final MethodHandle sqrt = Linker.nativeLinker()
        .downcallHandle(
            MATH.find("sqrt").orElseThrow(),
            FunctionDescriptor.of(ValueLayout.JAVA_DOUBLE, ValueLayout.JAVA_DOUBLE)
        );

    public static double sqrt(double x) throws Throwable {
        return (double) sqrt.invokeExact(x);
    }

    public static void main(String[] args) throws Throwable {
        System.out.println("sqrt(4) = " + sqrt(4)); // 输出: sqrt(4) = 2.0
    }
}

Java 21 (2023, LTS, ⭐⭐⭐⭐⭐)

  • 虚拟线程(正式) :正式发布 Project Loom,实现万级线程轻量化。由 JVM 调度,可创建数百万个线程而几乎不消耗 OS 线程资源。
import java.util.concurrent.*;

public class VirtualThreadsDemo {
    public static void main(String[] args) throws InterruptedException {
        // 1. 直接启动虚拟线程
        Thread.startVirtualThread(() -> {
            System.out.println("Running in a virtual thread: " + Thread.currentThread());
        });

        // 2. 使用 Executor(推荐)
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            IntStream.range(0, 1_000_000).forEach(i ->
                executor.submit(() -> {
                    // 模拟 I/O 等待
                    Thread.sleep(Duration.ofMillis(1));
                    return i;
                })
            );
        } // 自动关闭,等待所有任务完成
        System.out.println("1M 虚拟线程任务执行完毕");
    }
}
  • 序列集合 API:提供严格顺序的集合操作。
import java.util.*;

public class SequencedCollectionsDemo {
    public static void main(String[] args) {
        // List 示例
        List<Integer> list = new ArrayList<>(List.of(1, 2, 3));
        list.addFirst(0);           // [0, 1, 2, 3]
        list.addLast(4);            // [0, 1, 2, 3, 4]
        System.out.println(list.getFirst() + " " + list.getLast()); // 0 4
        System.out.println(list.reversed()); // [4, 3, 2, 1, 0]

        // Map 示例
        SequencedMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "One");
        map.put(2, "Two");
        map.putFirst(0, "Zero");    // {0=Zero, 1=One, 2=Two}
        map.putLast(3, "Three");    // {0=Zero, 1=One, 2=Two, 3=Three}
        System.out.println(map.firstEntry()); // 0=Zero
        System.out.println(map.reversed());   // {3=Three, 2=Two, 1=One, 0=Zero}
    }
}
  • 分代 ZGC:优化 ZGC 的垃圾回收性能。
  • 字符串模板:简化字符串拼接(如 SQL、JSON)。用 ${} 占位符直接在字符串中嵌入表达式,编译期完成插值,比 String.format() 更直观、更安全。
public class StringTemplatesDemo {
    public static void main(String[] args) {
        String name = "Kimi";
        int age = 25;

        // STR 处理器:直接插值
        String greeting = STR."Hello, \{name}! You are \{age} years old.";
        System.out.println(greeting); // 输出: Hello, Kimi! You are 25 years old.

        // FMT 处理器:支持格式化
        String formatted = FMT."%1$10s %2$5d".formatted(name, age);
        System.out.println(formatted); // 输出:       Kimi    25
    }
}
  • 结构化并发:正式发布简化多线程编程的 API。
import java.util.concurrent.*;

public class StructuredConcurrencyDemo {
    record Response(String user, int order) {}

    static Response handle() throws ExecutionException, InterruptedException {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            Future<String> user  = scope.fork(() -> findUser());
            Future<Integer> order = scope.fork(() -> fetchOrder());

            scope.join();                 // 等待全部完成或第一个失败
            scope.throwIfFailed();        // 如有异常则抛出

            return new Response(user.resultNow(), order.resultNow());
        }
    }

    static String findUser() { return "Alice"; }
    static int fetchOrder()  { return 42; }

    public static void main(String[] args) throws Exception {
        Response r = handle();
        System.out.println(r); // Response[user=Alice, order=42]
    }
}

Java 22 (2024, ⭐⭐)

  • 未命名变量(预览) :简化临时变量声明。
import java.util.List;
import java.util.stream.Collectors;

public class UnnamedVariablesDemo {
    public static void main(String[] args) {
        // 1. 遍历集合时忽略元素
        List<String> list = List.of("a", "b", "c");
        long count = 0;
        for (var _ : list) {  // 使用 _ 代替未使用的变量名
            count++;
        }
        System.out.println("元素个数: " + count); // 3

        // 2. Stream 中忽略 lambda 参数
        var map = list.stream()
                      .collect(Collectors.toMap(String::toUpperCase, _ -> Boolean.TRUE));
        System.out.println(map); // {A=true, B=true, C=true}

        // 3. 异常处理中忽略异常对象
        try {
            Integer.parseInt("abc");
        } catch (NumberFormatException _) {  // 使用 _ 忽略异常对象
            System.out.println("转换失败");
        }
    }
}
  • String 模板(预览) :进一步优化字符串拼接语法。
public class StringTemplatesDemo {
    public static void main(String[] args) {
        String name = "Demo";
        int age = 25;

        // 使用字符串模板
        String greeting = STR."Hello, \{name}! You are \{age} years old.";
        System.out.println(greeting); // Hello, Demo! You are 25 years old.

        // 格式化模板
        String formatted = FMT."%1$10s %2$5d".formatted(name, age);
        System.out.println(formatted); //       Kimi    25
    }
}

Java 23 (2024, ⭐⭐⭐)

  • Vector API(正式) :利用 SIMD 指令加速数值计算。
import jdk.incubator.vector.*;          // 引入孵化模块
import java.util.Arrays;

public class VectorAdditionDemo {
    public static void main(String[] args) {
        // 1. 初始化两个 float 数组
        float[] a = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
        float[] b = {8.0f, 7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
        float[] c = new float[a.length]; // 结果数组

        // 2. 获取当前平台最优向量种类(如 AVX-512 或 NEON)
        VectorSpecies<Float> species = FloatVector.SPECIES_PREFERRED;

        // 3. 主循环:按向量长度分块处理
        int i = 0;
        int upperBound = species.loopBound(a.length); // 计算对齐边界
        for (; i < upperBound; i += species.length()) {
            // 3.1 从数组加载向量
            FloatVector va = FloatVector.fromArray(species, a, i);
            FloatVector vb = FloatVector.fromArray(species, b, i);

            // 3.2 向量加法
            FloatVector vc = va.add(vb);

            // 3.3 将结果写回数组
            vc.intoArray(c, i);
        }

        // 4. 尾部标量处理(剩余不足一个向量的元素)
        for (; i < a.length; i++) {
            c[i] = a[i] + b[i];
        }

        // 5. 输出结果
        System.out.println("结果数组: " + Arrays.toString(c));
        // 输出: [9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0]
    }
}
  • 分代 ZGC 优化:进一步优化分代 ZGC 的垃圾回收效率。
# 只需启用 ZGC,默认即为分代模式
java -XX:+UseZGC -jar myapp.jar

# 若仍使用非分代模式会收到弃用警告
java -XX:+UseZGC -XX:-ZGenerational -jar myapp.jar

Java 24 (2025, ⭐⭐⭐⭐)

1. Vector API(正式转正)

JEP 489
利用 CPU 的 SIMD 指令集(如 AVX-512、NEON)并行加速数值计算,性能提升可达 8-16 倍。

import jdk.incubator.vector.*;          // 正式模块,无需 --add-modules
import java.util.Arrays;

public class VectorApiDemo {
    public static void main(String[] args) {
        float[] a = {1, 2, 3, 4, 5, 6, 7, 8};
        float[] b = {8, 7, 6, 5, 4, 3, 2, 1};
        float[] c = new float[a.length];

        // 自动选择最优向量种类(如 AVX-512)
        VectorSpecies<Float> species = FloatVector.SPECIES_PREFERRED;

        // 向量化主循环
        for (int i = 0; i < species.loopBound(a.length); i += species.length()) {
            FloatVector va = FloatVector.fromArray(species, a, i);
            FloatVector vb = FloatVector.fromArray(species, b, i);
            va.add(vb).intoArray(c, i);
        }

        // 尾部标量处理
        for (int i = species.loopBound(a.length); i < a.length; i++) {
            c[i] = a[i] + b[i];
        }

        System.out.println(Arrays.toString(c)); // [9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0]
    }
}

2. 分代 ZGC 默认启用

JEP 497
分代 ZGC 成为默认垃圾回收器,非分代模式被标记为废弃,未来版本将移除。

# 无需额外参数,直接使用分代 ZGC
java -XX:+UseZGC -jar myapp.jar

# 若强制使用非分代模式会收到弃用警告
java -XX:+UseZGC -XX:-ZGenerational -jar myapp.jar

3. Stream Gatherers(稳定)

JEP 485
提供自定义流中间操作,实现滑动窗口、去重、状态转换等复杂逻辑。

import java.util.List;
import java.util.stream.*;
import java.util.stream.Gatherer.*;

public class StreamGatherersDemo {
    public static void main(String[] args) {
        // 滑动窗口(每 3 个元素一组)
        List<List<Integer>> windows = Stream.of(1, 2, 3, 4, 5, 6, 7)
                .gather(Gatherers.windowFixed(3))
                .toList();
        System.out.println(windows); // [[1, 2, 3], [4, 5, 6], [7]]

        // 按字符串长度去重
        List<String> distinctByLen = Stream.of("foo", "bar", "baz", "quux")
                .gather(distinctByLength())
                .toList();
        System.out.println(distinctByLen); // [foo, quux]
    }

    // 自定义 Gatherer:按字符串长度去重
    static <T> Gatherer<T, Set<Integer>, T> distinctByLength() {
        return Gatherer.ofSequential(
                HashSet::new,
                (state, element, downstream) -> {
                    int len = element.toString().length();
                    if (state.add(len)) downstream.push(element);
                    return true;
                }
        );
    }
}

4. 量子抗性数字签名(ML-DSA)

JEP 496
引入抗量子计算的模块晶格签名算法,为长期安全性提供保障。

import java.security.*;

public class QuantumSafeDemo {
    public static void main(String[] args) throws Exception {
        // 生成 ML-DSA 密钥对
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-DSA");
        KeyPair kp = kpg.generateKeyPair();

        // 签名与验证
        Signature sig = Signature.getInstance("ML-DSA");
        sig.initSign(kp.getPrivate());
        sig.update("data".getBytes());
        byte[] signature = sig.sign();

        sig.initVerify(kp.getPublic());
        sig.update("data".getBytes());
        boolean valid = sig.verify(signature);

        System.out.println("签名验证: " + valid); // true
    }
}

5. 类文件 API(稳定)

JEP 484
提供标准 API 解析、生成和转换 Java 类文件,替代 ASM 等第三方库。

import java.lang.classfile.*;
import java.nio.file.*;

public class ClassFileApiDemo {
    public static void main(String[] args) throws Exception {
        // 读取类文件并打印字段
        ClassModel classModel = ClassFile.of().parse(Paths.get("Example.class"));
        System.out.println("类名: " + classModel.thisClass().asSymbol());
        classModel.fields().forEach(f ->
                System.out.println("字段: " + f.name() + " " + f.type().asSymbol())
        );
    }
}