顾乔芝士网

持续更新的前后端开发技术栈

Java8与Java21深度对比学习指南_java8与java21

Java 从 Java 8 到 Java 21 经历了巨大的演进,本指南将从基础到高级,全面系统地对比这两个长期支持版本(LTS)的主要差异,帮助开发者深入理解并掌握现代 Java 开发的核心技术。

第一部分:基础特性对比

1. 语言特性增强

Java 8 引入的核心特性

Lambda 表达式

// Java 8 之前
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return a.compareTo(b);
    }
});

// Java 8 Lambda
Collections.sort(list, (a, b) -> a.compareTo(b));

Lambda 表达式是 Java 8 最重大的改进之一,它使得 Java 具备了函数式编程的能力。Lambda 表达式由三部分组成:

  • 参数列表:(a, b)
  • 箭头符号:->
  • 表达式或语句块:a.compareTo(b)

方法引用

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

// 实例方法引用
list.forEach(String::toUpperCase);

// 构造方法引用
Supplier<List<String>> listSupplier = ArrayList::new;

方法引用进一步简化了 Lambda 表达式的写法,使代码更加简洁易读。

Stream API

List<String> result = list.stream()
    .filter(s -> s.startsWith("A"))
    .map(String::toLowerCase)
    .sorted()
    .collect(Collectors.toList());

Stream API 提供了对集合数据进行函数式操作的能力,主要特点包括:

  • 惰性求值:中间操作不会立即执行
  • 管道化:可以串联多个操作
  • 内部迭代:不需要显式编写循环语句

Java 21 新增/改进的特性

记录类 (Record)

public record Person(String name, int age, String address) {
    // 自动生成:
    // 1. 全参数构造方法
    // 2. 访问器方法 name(), age(), address()
    // 3. equals(), hashCode(), toString()
}

// 使用示例
Person person = new Person("Alice", 30, "New York");
System.out.println(person.name()); // 访问字段

记录类的主要特点:

  • 不可变性:所有字段默认是 final 的
  • 透明数据载体:自动生成标准方法
  • 简洁语法:大幅减少样板代码

模式匹配 (Pattern Matching)

// instanceof 模式匹配
if (obj instanceof String s && s.length() > 5) {
    System.out.println("长字符串: " + s);
}

// switch 模式匹配
String formatted = switch (obj) {
    case Integer i -> String.format("整数: %d", i);
    case Double d -> String.format("浮点数: %f", d);
    case String s -> String.format("字符串: %s", s);
    case null -> "null";
    default -> obj.toString();
};

模式匹配的优势:

  • 减少类型检查和强制转换的样板代码
  • 使代码更加直观和安全
  • 结合记录类使用时特别强大

文本块 (Text Blocks)

// Java 8 方式
String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world!</p>\n" +
              "    </body>\n" +
              "</html>";

// Java 21 文本块
String html = """
              <html>
                  <body>
                      <p>Hello, world!</p>
                  </body>
              </html>
              """;

文本块特性:

  • 保留原始格式,包括换行和缩进
  • 自动处理行终止符
  • 支持转义序列
  • 特别适合HTML、SQL、JSON等多行字符串

2. 集合框架改进

Java 8 集合改进

  • 新增 Collection.removeIf(), List.replaceAll(), List.sort() 等默认方法
  • Map 接口新增 compute(), merge(), getOrDefault() 等方法
  • ConcurrentHashMap 性能优化,新增流式操作方法

Java 21 集合改进

  • 序列化集合 (Sequenced Collections)
List<Integer> list = new ArrayList<>();
list.addFirst(1);   // 头部插入
list.addLast(2);    // 尾部插入
int first = list.getFirst();  // 获取第一个元素
int last = list.getLast();    // 获取最后一个元素
  • 不可变集合工厂方法
List<String> immutableList = List.of("a", "b", "c");
Set<Integer> immutableSet = Set.of(1, 2, 3);
Map<String, Integer> immutableMap = Map.of("a", 1, "b", 2);
  • 集合与流之间的转换更便捷
// 直接通过集合创建流
List<String> list = ...;
Stream<String> stream = list.stream();

// 流收集为不可变集合
List<String> newList = stream.collect(Collectors.toUnmodifiableList());

3. 日期时间 API

Java 8 引入的 java.time 包

// 本地日期时间
LocalDate today = LocalDate.now();
LocalTime now = LocalTime.now();
LocalDateTime current = LocalDateTime.now();

// 时区日期时间
ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));

// 时间差计算
Duration duration = Duration.between(startTime, endTime);
Period period = Period.between(startDate, endDate);

// 格式化和解析
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = current.format(formatter);
LocalDateTime parsed = LocalDateTime.parse("2025-08-18 14:30:00", formatter);

Java 21 日期时间改进

  • 新增 DateTimeFormatterBuilder.appendDayPeriodText()
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendPattern("yyyy-MM-dd ")
    .appendDayPeriodText()
    .toFormatter();
String formatted = LocalDateTime.now().format(formatter); // "2025-08-18 下午"
  • 增强的时区支持
// 获取所有可用时区
Set<String> zoneIds = ZoneId.getAvailableZoneIds();

// 时区转换
ZonedDateTime newYorkTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
ZonedDateTime shanghaiTime = newYorkTime.withZoneSameInstant(ZoneId.of("Asia/Shanghai"));

第二部分:中级特性对比

1. 并发编程改进

Java 8 并发特性

  • CompletableFuture 引入
CompletableFuture.supplyAsync(() -> fetchData())
    .thenApply(data -> processData(data))
    .thenAccept(result -> storeResult(result))
    .exceptionally(ex -> handleError(ex));
  • 新增 StampedLock 乐观读锁
StampedLock lock = new StampedLock();
long stamp = lock.tryOptimisticRead();
// 读操作
if (!lock.validate(stamp)) {
    stamp = lock.readLock();
    try {
        // 重新读操作
    } finally {
        lock.unlockRead(stamp);
    }
}
  • 并发累加器 (LongAdder, DoubleAdder)
LongAdder adder = new LongAdder();
IntStream.range(0, 100).parallel().forEach(i -> adder.add(i));
long sum = adder.sum();

Java 21 虚拟线程 (Virtual Threads)

// 创建虚拟线程
Thread.startVirtualThread(() -> {
    System.out.println("Running in virtual thread");
});

// 使用虚拟线程执行器
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}

// 结构化并发
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Future<String> user = scope.fork(() -> findUser(userId));
    Future<Integer> order = scope.fork(() -> fetchOrder(orderId));
    
    scope.join();
    scope.throwIfFailed();
    
    return new Response(user.resultNow(), order.resultNow());
}

虚拟线程的关键优势:

  • 轻量级:每个虚拟线程仅需约1KB内存
  • 高吞吐:可创建数百万个虚拟线程
  • 简单编程模型:保持同步代码风格
  • 自动调度:阻塞操作不会占用OS线程

2. Optional 类的改进

Java 8 Optional

Optional<String> optional = Optional.ofNullable(getString());

// 存在时执行操作
optional.ifPresent(System.out::println);

// 不存在时提供默认值
String value = optional.orElse("default");

// 链式操作
optional.map(String::toUpperCase)
       .filter(s -> s.length() > 5)
       .orElseThrow();

Java 21 Optional 增强

// ifPresentOrElse
optional.ifPresentOrElse(
    value -> System.out.println("Found: " + value),
    () -> System.out.println("Not found"))
);

// or
Optional<String> fallback = optional.or(() -> Optional.of("fallback"));

// stream
Stream<String> stream = optional.stream();

3. 接口的演变

Java 8 接口

public interface MyInterface {
    // 抽象方法
    void abstractMethod();
    
    // 默认方法
    default void defaultMethod() {
        System.out.println("Default implementation");
    }
    
    // 静态方法
    static void staticMethod() {
        System.out.println("Static method");
    }
}

Java 21 接口

public interface MyInterface {
    // 私有方法
    private void privateMethod() {
        System.out.println("Private method");
    }
    
    // 默认方法可以调用私有方法
    default void defaultMethod() {
        privateMethod();
        System.out.println("Default implementation");
    }
    
    // 密封接口
    sealed interface SealedInterface permits Implementation1, Implementation2 {}
}

第三部分:高级特性对比

1. 模块系统 (Java 9+)

Java 21 模块化

// module-info.java
module com.example.myapp {
    requires java.base;
    requires java.sql;
    requires transitive com.example.utils;
    
    exports com.example.myapp.api;
    opens com.example.myapp.internal to com.example.test;
}

模块化的关键概念:

  • 强封装:明确声明导出和开放的包
  • 显式依赖:必须声明所有依赖
  • 服务加载:通过 provides 和 uses 声明服务
  • 自定义运行时:使用 jlink 创建精简运行时

2. 垃圾回收器改进

Java 8 垃圾回收

  • 并行收集器 (Parallel GC):高吞吐量,适合批处理应用
  • CMS (Concurrent Mark-Sweep):低延迟,但会产生内存碎片
  • G1 (Garbage-First):需手动启用 (-XX:+UseG1GC)

Java 21 垃圾回收

  • G1 作为默认收集器
  • ZGC (Z Garbage Collector):亚毫秒级停顿
java -XX:+UseZGC -Xmx4g -jar myapp.jar
  • Shenandoah:低停顿时间的并发收集器
java -XX:+UseShenandoahGC -Xmx4g -jar myapp.jar

3. 性能优化

Java 21 性能改进

  • 启动时间优化:类数据共享 (CDS)
# 生成共享归档
java -Xshare:dump
# 使用共享归档
java -Xshare:on -jar myapp.jar
  • AOT 编译 (GraalVM Native Image)
native-image -jar myapp.jar
  • 向量 API (SIMD 指令)
var a = FloatVector.fromArray(FloatVector.SPECIES_256, arrayA, 0);
var b = FloatVector.fromArray(FloatVector.SPECIES_256, arrayB, 0);
var c = a.mul(b).add(a);
c.intoArray(result, 0);

4. 新API和工具

Java 21 新API

  • HTTP Client API
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://example.com/api"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"key\":\"value\"}"))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
  • 进程 API 增强
ProcessHandle current = ProcessHandle.current();
System.out.println("PID: " + current.pid());
System.out.println("Command: " + current.info().command().orElse("unknown"));

ProcessHandle.allProcesses()
    .filter(p -> p.info().user().equals("alice"))
    .forEach(p -> System.out.println(p.pid()));
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言