前言
JDK 21
自发布以来,正好有契机,新项目使用了这一长期稳定的版本。经过一年的开发工作,现在我将从实际开发中的编码体验和实际的提升两个角度,分享使用感受。
对比条件说明:
本文将重点对比JDK 8
和JDK 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 8
、springboot 2.0
对比JDK 21
、springboot 3.0
内存占用情况如下:
对比可以看出JDK 21
比JDK 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 的提升
- 引入现代化特性(
var
、record
等),减少样板代码。 - 性能显著优化:如 ZGC 和 G1 垃圾收集器改进。
总结
影响方面 | JDK 8 | JDK 21 |
---|---|---|
代码简洁性 | 样板代码多,拼接繁琐 | 现代化语法减少样板代码 |
设计模式支持 | 类继承限制较少 | sealed 类提升安全性 |
函数式编程 | 初步支持 | 更完善,类型推断增强 |
数据结构 | 无 Record | Record 更高效 |
性能优化 | 基础优化 | 垃圾回收和编译性能提升 |
最后:
无论是使用JDK 8
还是JDK 21
,都需要根据项目实际情况做出选择。值得注意的是,新技术的引入往往伴随着一定的学习成本。
希望这篇文章能够帮助大家更好地了解JDK 21
,并在未来的开发中对JDK
的选择有更清晰的判断和深入的理解。