Bootstrap

JDK 21 使用一年的总结与感悟,全部分享!

前言

JDK 21 自发布以来,正好有契机,新项目使用了这一长期稳定的版本。经过一年的开发工作,现在我将从实际开发中的编码体验实际的提升两个角度,分享使用感受。

对比条件说明:
本文将重点对比 JDK 8JDK 21,因为有对比才能有更直观的感受。


1. 实际开发中的编码体验

1.1. 新的语法变化和增强点

接口的私有方法

接口允许定义私有方法,方便代码复用且保持接口设计清晰。

interface MyInterface {
    private void myPrivateMethod() {
        // 私有方法
    }
}
局部变量类型推断(var

减少手动声明变量类型的繁琐性,并支持在 Lambda 表达式中使用 var

var list = new ArrayList<String>();

BiConsumer<String, String> consumer = (var a, var b) -> {
    System.out.println("a: " + a + ", b: " + b);
};
字符串处理的新方法
  • isBlank():检查字符串是否为空或仅包含空格。
  • lines():将多行字符串转换为流。
  • repeat():将字符串重复指定次数。
String multiline = "Line 1\nLine 2\nLine 3";
var lines = multiline.lines().collect(Collectors.toList());
System.out.println(lines); // 输出:[Line 1, Line 2, Line 3]
Switch 表达式增强

支持返回值,且可以使用更简洁的 Lambda 风格语法。

String message = switch (day) {
    case "MONDAY" -> "Start of the week";
    case "FRIDAY" -> "End of the work week";
    default -> "Midweek";
};
多行字符串(Text Block)

使用 """ 定义多行字符串,自动处理换行,减少手动拼接字符串的复杂性。

String textBlock = """
    Hello, this is a text block!
    You can write across multiple lines.
""";
模式匹配(Pattern Matching)

语法增强,直接在条件语句中绑定变量并进行类型转换。

if (obj instanceof String str) {
    System.out.println("String: " + str.length());
}
Sealed 类

通过限制子类的类型范围,增强类层次结构的封装性和安全性。

sealed class Animal permits Dog, Cat {}
final class Dog extends Animal {}
final class Cat extends Animal {}
Record 类

用于表示不可变数据对象,自动生成常见方法(如构造器、equals()hashCode()toString() 等)。

public record Point(int x, int y) {}
字符串模板(String Template)

提供更简单的字符串插值方式,减少拼接字符串的繁琐性。

String name = "张三";
int age = 30;
String message = STR."Hello, \{name}! You are \{age} years old.";
一些其它的变化…
  • 增强的异常处理: 对特定异常的捕获和处理可能更加灵活。
  • 泛型的改进: 某些场景下的泛型推导可能更智能。
  • 更多 API 改进: 某些核心库方法在性能或功能上可能得到优化。
  • 虚拟线程: 解决传统线程的性能和资源消耗问题。

1.2. 其他使用感受

内存占用变小

分别使用的JDK 8springboot 2.0对比JDK 21springboot 3.0内存占用情况如下:

对比可以看出JDK 21JDK 8更加节省内存,理论上来说,项目越“臃肿”时差距越明显,可以看出新版本优化还是用心了的👍。

运行速度提升

由于参与了多个基于 JDK 8 的大项目,也使用过多个基于 JDK 21 的大项目,最大的感受是项目启动速度上的明显差异。不过,这里没有进行同条件对比测试,因为大项目切换JDK涉及的兼容性改动太多,无法实测,请诸位谅解😅。


过渡说明:
实际开发中能够明显感受到以上这些差别。
接下来,我将简单分享一些通过整理资料总结出的实际的提升
由于本文的重点在于分享实际体验,而关于JDK升级变化的详细资料也很容易查找,因此这里只做简要概述。


2. 实际的提升

2.1. 代码简洁性和可读性

JDK 8 的局限性
  • 需要手动定义变量类型,多行字符串需要手动拼接。
  • switch 语句相对冗长。
JDK 21 的提升
  • 使用 var 简化变量声明。
  • 多行字符串 """ 避免拼接。
  • switch 表达式更短更安全。
var x = 10;
String message = """
Hello World!
This is JDK 21.
""";
String result = switch (day) {
    case "MONDAY" -> "Start of the week";
    default -> "Unknown";
};

2.2. 面向对象设计扩展性

JDK 8 的局限性
  • 接口仅支持默认和静态方法。
  • 缺少 sealed 类,类层次结构难以限制。
JDK 21 的提升
  • 接口支持私有方法,增强代码复用。
  • 引入 sealed 类,限制子类继承范围。
sealed class Animal permits Dog, Cat {}
interface MyInterface {
    private void helper() {
        System.out.println("Helper logic");
    }
}

2.3. 函数式编程支持增强

JDK 8 的局限性
  • 类型推断能力有限,需手动声明变量类型。
  • Stream 操作写法略显冗长。
JDK 21 的提升
  • 在 Lambda 表达式中支持 var
  • 增强 Stream API,例如字符串的 lines() 方法。
BiConsumer<String, String> consumer = (var a, var b) -> System.out.println(a + b);
var lines = "Line1\nLine2".lines().collect(Collectors.toList());

2.4. 数据结构与模式匹配

JDK 8 的局限性
  • 类型检查需手动转换,样板代码多。
  • 缺少原生不可变对象支持。
JDK 21 的提升
  • 增强 instanceof,支持模式匹配。
  • 引入 Record,快速定义不可变数据对象。
if (obj instanceof Integer num) {
    System.out.println(num * 2);
}
public record Point(int x, int y) {}

2.5. 字符串操作能力

JDK 8 的局限性
  • 缺少内置多行字符串支持。
  • 字符串拼接容易冗长。
JDK 21 的提升
  • 多行字符串(""")简化复杂文本处理。
  • 新增字符串方法(如 repeat())。
String text = """
Hello
World
""";
System.out.println(text.repeat(3));

2.6. 开发效率与性能

JDK 8 的局限性
  • 样板代码多,开发效率受限。
  • 性能优化不及新版本(如 GC 改进)。
JDK 21 的提升
  • 引入现代化特性(varrecord 等),减少样板代码。
  • 性能显著优化:如 ZGC 和 G1 垃圾收集器改进。

总结

影响方面JDK 8JDK 21
代码简洁性样板代码多,拼接繁琐现代化语法减少样板代码
设计模式支持类继承限制较少sealed 类提升安全性
函数式编程初步支持更完善,类型推断增强
数据结构RecordRecord 更高效
性能优化基础优化垃圾回收和编译性能提升

最后:
无论是使用 JDK 8 还是 JDK 21,都需要根据项目实际情况做出选择。值得注意的是,新技术的引入往往伴随着一定的学习成本。
希望这篇文章能够帮助大家更好地了解 JDK 21,并在未来的开发中对 JDK 的选择有更清晰的判断和深入的理解。

;