很多人公司里还跑着 Java 6、Java 7 的老项目。
你打开代码一看:
- 满屏
new ArrayList<String>() try-finally手动关流switch只能写case 1:- 日期处理靠
Date - 多线程靠手搓
Thread - JSON 解析全是工具类大战
而现在已经是 Java 21 的时代了。
Java 21 是 LTS(长期支持版),距离 Java 6 已经跨越了十几年的语言演进。很多当年“写 Java 很啰嗦”的痛点,今天其实都已经被官方解决了。
这篇文章不讲历史八卦,直接看:
Java 21 相比 Java 6,到底多了哪些真正影响开发体验的特性?
并且每个特性都配实际代码。
一、类型推断:终于不用写两遍类型了(var)
Java 6 写法
Map<String, List<User>> userMap = new HashMap<String, List<User>>();
老 Java 最大的问题:
你声明一次类型,还要再重复一次。
非常烦。
Java 21 写法
var userMap = new HashMap<String, List<User>>();
甚至:
var name = "Tom";
var age = 18;
var list = List.of("A", "B", "C");
代码一下清爽很多。
什么时候别用 var?
这个很多人容易走极端。
下面这种:
var x = doSomething();
如果方法名语义不明显,可读性会下降。
所以:
- 类型明显 → 用 var
- 类型不明显 → 老老实实写类型
这才是正确姿势。
二、集合工厂方法:告别一长串 add()
Java 6
List<String> list = new ArrayList<String>();
list.add("Java");
list.add("Python");
list.add("Go");
Java 21
var list = List.of("Java", "Python", "Go");
Map 也支持:
var map = Map.of(
"name", "Tom",
"age", "18"
);
这个改动看起来小。
但实际开发里:
代码量减少非常明显。
尤其是测试代码。
三、Lambda 表达式:Java 终于不像老干部了
Java 6
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
}).start();
匿名内部类写到怀疑人生。
Java 21
new Thread(() -> System.out.println("hello")).start();
差距已经不是“一点点”。
四、Stream API:集合处理进入现代时代
Java 6 那会儿最经典的代码:
List<String> result = new ArrayList<String>();
for (String item : list) {
if (item.startsWith("J")) {
result.add(item.toUpperCase());
}
}
Java 21:
var result = list.stream()
.filter(item -> item.startsWith("J"))
.map(String::toUpperCase)
.toList();
Stream 最大的价值不是“炫技”。
而是:
- 业务逻辑表达更清晰
- 更适合并行处理
- 更接近函数式思维
当然。
别为了 Stream 而 Stream。
有些复杂逻辑硬写链式调用,只会越来越难维护。
五、Text Block:终于不用疯狂拼字符串了
Java 6
String json = "{\n" +
" "name": "Tom",\n" +
" "age": 18\n" +
"}";
看着都累。
Java 21
String json = """
{
"name": "Tom",
"age": 18
}
""";
写 SQL 特别爽:
String sql = """
SELECT id, name
FROM user
WHERE age > 18
""";
这个特性一旦用了,就回不去了。
六、Switch 表达式:终于不像上世纪语法了
Java 6
String result;
switch (code) {
case 1:
result = "SUCCESS";
break;
case 2:
result = "FAIL";
break;
default:
result = "UNKNOWN";
}
Java 21
var result = switch (code) {
case 1 -> "SUCCESS";
case 2 -> "FAIL";
default -> "UNKNOWN";
};
没有 break。
没有变量提前声明。
没有 case 穿透。
舒服很多。
七、Record:DTO 不再是样板代码地狱
以前 Java Bean:
public class User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return ...
}
}
真正业务代码没几行。
Getter/Setter 写了一堆。
Java 21:
public record User(String name, Integer age) {
}
自动生成:
- 构造器
- getter
- equals
- hashCode
- toString
尤其适合:
- DTO
- 返回对象
- 查询结果对象
八、Pattern Matching:instanceof 终于不反人类了
Java 6
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}
Java 21
if (obj instanceof String str) {
System.out.println(str.length());
}
少一次强转。
但开发体验提升巨大。
这种优化特别“润物细无声”。
九、虚拟线程(Virtual Thread):Java 并发真正的大升级
这个是 Java 21 里最重量级的能力之一。
以前:
ExecutorService executor = Executors.newFixedThreadPool(200);
线程很贵。
不敢开太多。
Java 21:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10000; i++) {
executor.submit(() -> {
Thread.sleep(1000);
return null;
});
}
}
你甚至可以轻松开几十万级任务。
为什么重要?
传统线程:
- 1 个线程 ≈ 1 个操作系统线程
- 成本高
- 内存占用大
虚拟线程:
- JVM 管理
- 极轻量
- 特别适合 IO 密集型场景
比如:
- Web 服务
- RPC 调用
- 数据库访问
很多以前必须上 Reactor、异步回调才能扛住的场景。
现在同步代码都能跑很高并发。
这对 Java 生态影响非常大。
十、新的日期时间 API:终于不用 Date 了
Java 6 的日期 API:
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
问题:
- API 设计混乱
- 线程不安全
- 时区容易炸
Java 21:
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plusWeeks(1);
System.out.println(nextWeek);
格式化:
var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
System.out.println(today.format(formatter));
这是 Java 生态里非常成功的一次 API 重构。
十一、Optional:少写很多 null 判断
Java 6
if (user != null && user.getAddress() != null) {
System.out.println(user.getAddress().getCity());
}
Java 21
Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity)
.ifPresent(System.out::println);
当然。
Optional 不是让你 everywhere 都用。
它更适合:
- 返回值
- 链式空值处理
而不是:
Optional<String> name;
这种字段级滥用。
十二、模块化(JPMS)
Java 9 引入。
以前:
- Jar 地狱
- 包冲突
- 类路径混乱
现在:
module com.demo.app {
requires java.sql;
}
大型项目治理会舒服很多。
不过现实里:
很多公司还没真正用起来。
十三、SequencedCollection:集合终于有“头尾”统一操作了
Java 21 新特性。
以前:
LinkedList<String> list = new LinkedList<>();
list.addFirst("A");
list.addLast("B");
不同集合 API 不统一。
Java 21:
SequencedCollection<String> list = new LinkedList<>();
list.addFirst("A");
list.addLast("B");
统一了:
- first
- last
- reverse
集合 API 更规整。
十四、字符串增强
repeat()
"-".repeat(10);
isBlank()
str.isBlank();
lines()
text.lines().forEach(System.out::println);
这些看似“小功能”。
但天天写业务的人知道:
高频小优化,最提升幸福感。
十五、HTTP Client:终于不用 HttpURLConnection 了
Java 6:
HttpURLConnection conn = ...
又臭又长。
Java 21:
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
var response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
现代很多项目已经不一定需要第三方 HTTP 库了。
十六、GC 进化:性能不是一个时代
Java 6 时代主流:
- Serial GC
- Parallel GC
- CMS
而 Java 21:
- G1
- ZGC
- Shenandoah
暂停时间和吞吐能力已经完全不是一个时代。
尤其:
ZGC
目标:
超低停顿。
哪怕几十 GB 堆内存,也能做到非常低的 STW。
对于大内存服务非常关键。
十七、Preview 特性:Java 开始敢“进化”了
以前 Java 更新特别保守。
现在:
- Pattern Matching
- String Template
- Scoped Value
- Structured Concurrency
很多能力会先 Preview。
社区反馈后再正式发布。
这意味着:
Java 已经不是那个“十年不变”的语言了。
最后:Java 21 最大的变化,其实不是语法
很多人会觉得:
“不就是语法糖吗?”
其实不是。
Java 21 最大的变化是:
Java 开始重视“开发者体验”了
过去:
- 冗长
- 啰嗦
- 模板代码多
现在:
- 更现代
- 更简洁
- 更适合云原生
- 更适合高并发
尤其虚拟线程出来之后。
Java 在服务端领域的生命力,又被续了一大口。
如果现在还在 Java 6/7/8 怎么办?
建议路线:
- Java 8 → 至少升 17
- 新项目 → 直接 21
因为:
- 17/21 是 LTS
- 生态支持已经成熟
- 性能提升巨大
- 开发效率提升明显
很多老项目不升级,不是因为不能升。
而是:
“没人敢动。”
但越拖,技术债越重。
这几乎是所有 Java 老系统的共同命运。