Java 近几十年的版本迭代中,一直围绕两个核心目标:
提升开发效率 (语法更干净、API更强)
提升性能和可扩展性(线程、IO、JVM 更高效)
下面按时代划分,总结最重要且最常用的特性。
JDK 5 新特性(最重要:泛型)
JDK 5 是 Java 历史上一个"大升级"。
1. 泛型(Generics)
核心作用:
-
在编译期保证类型安全
-
避免强制类型转换
-
让集合等 API 更易用
示例:
java
List<String> list = new ArrayList<>();
String s = list.get(0); // 不需要 (String)
泛型在 编译期有效,运行期擦除。
(具体见上一篇泛型文章)
JDK 8 新特性(Java 的第二次飞跃)
JDK 8 是最最常用的 Java 版本,关键之处在于:
正式把 Java 带入了"函数式编程时代"。
包含 3 个核心特性:
1. Lambda 表达式(函数式编程核心)
本质就是对匿名内部类的一个简化,不再需要去new抽象类或者接口去写实体了,而是直接指定参数函数以及对应函数执行的代码。
本质:
把"一个函数"当成值传递,让代码更简洁。
例子:
java
list.forEach(s -> System.out.println(s));
匿名内部类不再成为噩梦。
2. Stream API
简单来说就是它不需要中间操作变量了,例如下面的list(res),而是直接通过流的形式,惰性计算,让代码更简洁。
本质:
让你用类似 SQL 的声明式方式处理集合数据。
示例:
不用流:
java
List<String> list = ...
List<String> res = new ArrayList<>();
for(String s : list) {
if(s.startsWith("a")){
res.add(s.toUpperCase());
}
}
用流:
java
list.stream()
.filter(s -> s.startsWith("a"))
.map(String::toUpperCase)
.toList();
它做了三件事:
-
把 list 转成"流"
-
过滤所有不以 "a" 开头的字符串
-
把剩下的字符串全部转大写
-
收集成一个新的 List 返回
看它是不是像 SQL:
java
SELECT UPPER(name)
FROM list
WHERE name LIKE 'a%';
优点:
-
流式链式写法优雅
-
支持并行
.parallelStream() -
异常强大:filter/map/reduce/grouping... 全都有
3. Optional(避免 NullPointerException)
传统写法:
java
if(x != null) x.getName();
Optional:
java
Optional.ofNullable(x).map(User::getName).orElse("default");
// 获取对象 x 的 name 属性,如果 x 为 null 或 name 为 null,则返回默认值 "default"。
→ 本质:强迫你显式处理 null,减少 NPE(NullPointerException )
JDK 21 新特性(虚拟线程的重要性)
形象理解:
-
虚拟线程 就像一个"挡灾难的小兵"------它发现即将遭遇阻塞(IO 等待)时,先 挂起自己,把操作系统线程让出来,让其他虚拟线程继续干活。
-
真正处理灾难的人 还是 操作系统线程,它在内核层处理 IO 的等待、读写等工作。
JDK21 是 长期支持版本(LTS),真正的大亮点就是:
虚拟线程(Virtual Thread)
Java 终于拥有像 Go 协程一样的能力。
为什么需要虚拟线程(Virtual Thread)?
传统线程(Platform Thread)的问题:
-
1 个 JVM 线程 = 1 个操作系统线程
-
一个进程最多大约 6 万个线程(OS 限制)
-
创建/切换线程开销大(系统调用 + 内核态切换)
-
BIO 阻塞会导致线程被挂起 → 高并发时线程耗尽
典型场景:Tomcat,一个请求一个线程模型
比如:
-
10000 个请求
-
每个请求阻塞 100ms 等数据库
传统做法:要创建 10000 个线程
→ 线程太多 CPU 反而闲着,但线程资源耗尽。
虚拟线程如何解决?
虚拟线程由 JVM 管理,不依赖 OS。
特点:
1. 超轻量
百万级虚拟线程不是问题。
2. 不需要线程池(池化也没意义)
创建一个虚拟线程几乎零成本。
3. 由少量平台线程承载
很多虚拟线程复用少量 OS 线程。
4. 阻塞不再昂贵
虚拟线程阻塞时,不会阻塞 OS 线程。
→ 可以安全使用同步阻塞 I/O(BIO)
→ 开发体验更简单,性能又高
虚拟线程如何切换?
就像 Go 协程:
-
虚拟线程有自己的 栈 和 程序计数器
-
阻塞时,JVM 会保存状态并切换到其他虚拟线程(无需 OS 参与)
-
切换成本极低,因为不进入内核态
生态支持
目前:
-
Spring Boot
-
Tomcat
-
Jetty
-
Netty(部分)
-
数据库驱动(部分)
-
Loom 项目本体
均已支持或计划全面支持。
Java 的并发模型正在被彻底改变。
总结一句话
| 版本 | 关键词 | 改变了什么 |
|---|---|---|
| JDK5 | 泛型 | 静态类型安全 |
| JDK8 | Lambda + Stream + Optional | 现代化语法、函数式编程 |
| JDK21 | 虚拟线程 | 高并发性能革命,能开百万线程 |
如果要一句最简单的记忆方式:
JDK5 解决类型安全,JDK8 解决开发效率,JDK21 解决并发性能瓶颈。