
"学长,面试官问JDK 8有什么新特性,我只能憋出个
Lambda...""我刚入职,项目用的是JDK 17,看到代码里的
var、record一脸懵...""书上写的J2SE、J2EE,怎么现在都叫Java SE了?"
如果你也有这些困惑,那这篇文章就是为你准备的。
我用了一整天时间,把Java从1996年诞生到今天的发展历程彻底梳理了一遍。看完这篇,你不仅知道每个版本有哪些重要特性,还能明白"为什么企业都用JDK 8"、"新项目该选JDK 17还是JDK 21"这些实际问题。
说实话,刚开始学Java时,看到"JDK 1.8"、"JDK 11"、"JDK 17"这些版本号就头疼。不是说学Java吗?怎么还有这么多版本?它们有什么区别?我该用哪个?
更让我崩溃的是,书上偶尔还会冒出“J2SE”、“J2EE”这种老古董词汇。后来怎么又变成“Java SE”、“Jakarta EE”了?还有人老说“JDK 和 JVM 的关系”……
后来我花了一整天时间查资料、画图,总算把这一团乱麻理清了。今天就把我的学习笔记分享出来,保证你看完这篇,以后再也不迷糊!
咱们先来玩个角色扮演,理清这些核心概念的关系。

很多初学者觉得"历史有什么用?会敲代码不就行了?"
错!大错特错!
举几个例子:
懂历史,才能看懂技术的演进逻辑,学新东西也更快!
1991 年,Sun 公司的詹姆斯·高斯林(James Gosling)带领团队启动了一个叫“Green”的项目,目标是为未来的智能家电(比如微波炉)写一套通用控制系统。
团队给这门新语言起名 Oak(橡树),灵感来源于高斯林办公室窗外的树。可惜,这个名字被别人注册了。后来,大家想起常去喝咖啡的一家店叫“Java”,于是,这个既好听又有代表性的名字就诞生了。这也是为什么 Java 的 Logo 是一杯热气腾腾的咖啡。
1996 年 1 月 23 日,JDK 1.0 正式发布,一句口号响彻全球:
“Write Once, Run Anywhere”(一次编写,到处运行)
这在当时简直是黑科技!同一份代码,不用任何修改,就能在 Windows、Mac、Linux 上跑,全靠 JVM 这个“万能翻译官”。那时候,一个叫 Applet 的东西让 Java 火遍大江南北——因为它能让网页动起来!
核心特性:
这个版本奠定了 Java 企业级应用的基石。最重要的更新就是 JDBC,它让 Java 连接数据库变得标准化,没有它,Java 想在企业后端当大哥?门儿都没有。
主要新特性:
这是一个里程碑式的版本,Sun 公司正式将 Java 平台一分为三:
平台 | 全称 | 用途 |
|---|---|---|
J2SE | Java 2 Standard Edition | 标准版,桌面应用开发的地基 |
J2EE | Java 2 Enterprise Edition | 企业版,服务器端、企业级应用的航空母舰 |
J2ME | Java 2 Micro Edition | 微型版,当年诺基亚、摩托罗拉手机上的游戏和应用 |
核心新特性:
小贴士:JDK 1.2引入了HotSpot虚拟机,后来成为Java性能优化的里程碑。
这两个版本主要是优化和增强:
JDK 1.3:
JDK 1.4:

如果说前面的版本是打基础,那 JDK 5 就是一次语言层面的核聚变。从它开始,Java 的命名规则也变了,不再叫“JDK 1.5”,而是直接叫“JDK 5”。
这个版本的新特性多到爆炸,我们用代码说话:
1. 泛型(Generics): 告别强制类型转换,拥抱安全
// 泛型前:类型不安全,需要强制转换
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0); // 需要强制转换,容易出错
// 泛型后:类型安全,代码更清晰
List<String> list = new ArrayList<>();
list.add("hello");
String s = list.get(0); // 不需要强制转换2. 增强for循环(for-each): 遍历集合从未如此优雅
// 之前
for (Iterator<String> i = list.iterator(); i.hasNext(); ) {
String s = i.next();
System.out.println(s);
}
// 现在
for (String s : list) {
System.out.println(s);
}3. 自动装箱/拆箱: 基本类型和包装类无缝切换
// 自动装箱:int -> Integer
Integer num = 10; // 编译器自动转为 new Integer(10)
// 自动拆箱:Integer -> int
int n = num; // 编译器自动转为 num.intValue()4. 枚举类型(Enum): 让常量定义更规范
// 之前:用常量
public static final int SPRING = 1;
public static final int SUMMER = 2;
// 现在:用枚举,更安全、更优雅
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}5. 注解(Annotations): 给代码打上标签,框架开发的利器
@Override // 标记重写方法
@Deprecated // 标记过时方法6. 可变参数
// 可变参数:参数数量可变
public void print(String... args) {
for (String s : args) {
System.out.println(s);
}
}
print("a", "b", "c"); // 可以传任意个参数7. 静态导入
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
// 直接使用,不用写Math.
double area = PI * r * r;
double d = sqrt(9);8. 并发工具增强
JDK 5还带来了java.util.concurrent包,里面有:
记忆口诀:JDK 5新特性记不住?记住"泛强自枚注可静"(泛型、增强for、自动装箱、枚举、注解、可变参数、静态导入)
主要聚焦于性能优化和易用性:
JDK 7 原计划有大动作(Lambda 表达式),但因 Sun 公司被 Oracle 收购而推迟。不过,它带来的几个小特性却非常实用:
1. try-with-resources(自动关闭资源): 妈妈再也不用担心我忘记关流了
// 之前:手动关闭,容易忘记
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try {
String line = br.readLine();
} finally {
br.close(); // 必须手动关闭
}
// 现在:自动关闭
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line = br.readLine();
} // 自动关闭,不用写finally2. 字符串switch: 终于不用写一堆 if-else 了
// 之前:只能用int、enum做switch
// 现在:字符串也可以!
String day = "MONDAY";
switch (day) {
case "MONDAY":
System.out.println("周一");
break;
case "TUESDAY":
System.out.println("周二");
break;
}3. 菱形操作符(Diamond Operator): 让代码更简洁
// 之前:泛型要写两边
List<String> list = new ArrayList<String>();
// 现在:右边不用重复写类型
List<String> list = new ArrayList<>();4. 二进制字面量
int binary = 0b1010; // 二进制
int underscore = 1_000_000; // 数字可以用下划线分隔JDK 8是迄今为止影响最深远的版本,没有之一!哪怕你现在用的是JDK 17、JDK 21,你每天写的代码也处处是 JDK 8 的影子。它改变了我们写 Java 代码的思维方式。
让 Java 正式拥抱函数式编程,代码量大幅减少。
// 之前:匿名内部类,啰嗦
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
// 现在:Lambda表达式,简洁
Runnable r = () -> System.out.println("Hello");
// 集合排序对比
list.sort(new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
// Lambda写法
list.sort((a, b) -> a.compareTo(b));操作集合就像写 SQL 查询语句一样,声明式、链式调用,爽到飞起。
// 之前:一步步处理
List<String> filtered = new ArrayList<>();
for (String s : list) {
if (s.length() > 3) {
filtered.add(s.toUpperCase());
}
}
// 现在:链式调用,声明式处理
List<String> filtered = list.stream()
.filter(s -> s.length() > 3) // 过滤
.map(String::toUpperCase) // 转换
.collect(Collectors.toList()); // 收集结果接口里可以写带方法体的方法了!
public interface MyInterface {
// 普通抽象方法
void doSomething();
// 默认方法:有默认实现
default void doSomethingElse() {
System.out.println("默认实现");
}
}终于告别难用的Date和Calendar了!
// JDK 8之前:Date和Calendar难用死了
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, 7);
// JDK 8:新的日期时间API
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plusDays(7);
LocalDateTime now = LocalDateTime.now();优雅地解决空指针异常(NullPointerException),告别丑陋的 if (obj != null) 判断。
// JDK 8之前
String name = getName();
if (name != null) {
System.out.println(name.length());
}
// JDK 8之后:用Optional包装
Optional<String> name = Optional.ofNullable(getName());
name.ifPresent(n -> System.out.println(n.length()));小贴士:JDK 8之所以这么重要,是因为Lambda、Stream、Optional这些特性改变了我们写Java的方式,让代码更简洁、更易读、更函数式。
将庞大的 JDK 拆分成一个个模块,让 Java 应用可以按需打包,为云原生时代铺路。
// module-info.java
module com.example.mymodule {
requires java.base; // 依赖其他模块
exports com.example.mymodule.api; // 导出包
}主要新特性:
// 之前:类型写在前面
String name = "Java";
ArrayList<String> list = new ArrayList<>();
// JDK 10:var自动推断类型
var name = "Java";
var list = new ArrayList<String>();继 JDK 8 之后第一个被企业大规模采用的 LTS 版本。带来了标准化的 HttpClient API 和实验性的低延迟垃圾回收器 ZGC。
主要特性:
从JDK 12开始,Java引入了 预览特性(Preview Features) 机制:
JDK 12-13:新式 Switch 表达式
// JDK 13+:新的Switch表达式
int days = switch (month) {
case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> 31;
case APR, JUN, SEP, NOV -> 30;
case FEB -> {
if (isLeapYear) yield 29;
else yield 28;
}
};JDK 13-15:Text Blocks(文本块)
// 之前:字符串拼接
String html = "<html>\n" +
" <body>\n" +
" <p>Hello</p>\n" +
" </body>\n" +
"</html>";
// JDK 15+:文本块(优雅~~~)
String html = """
<html>
<body>
<p>Hello</p>
</body>
</html>
""";JDK 14-16:Records(记录类)
// 之前:写一个数据类要一大堆代码
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getter、equals、hashCode、toString...
}
// JDK 16+:用record一键生成
public record Person(String name, int age) {}JDK 15-17:Sealed Classes(密封类)
// 限制类的继承关系
public sealed class Shape permits Circle, Rectangle, Square {
}
public final class Circle extends Shape {} // final:不能再继承
public sealed class Rectangle extends Shape {} // sealed:可以继续被继承
public non-sealed class Square extends Shape {} // non-sealed:随便继承现代Java的标配!Spring Boot 3.x要求JDK 17+。
正式发布的特性:
JDK 21 的虚拟线程(Virtual Threads) 正式发布,这是一项颠覆性的技术。它可以让你在一个应用中轻松创建和管理上百万个并发线程,且几乎不消耗系统资源。
// 之前:传统线程,创建成本高
Thread thread = new Thread(() -> doWork());
thread.start();
// JDK 21+:虚拟线程,轻量级,可以创建百万个
Thread.startVirtualThread(() -> doWork());
// 或者用构建器
Thread virtualThread = Thread.ofVirtual()
.name("my-vt")
.start(() -> doWork());一句话总结:高并发编程的门槛被 JDK 21 砸平了。
1. 版本号混淆
2. LTS 版本选择坑
参考回答:
java.time包,替代Date和Calendar。参考回答:
JDK 8是Java历史上最重要的版本,原因有三点:
阶段 | 版本 | 核心意义 |
|---|---|---|
诞生 | JDK 1.0 | 跨平台理念,Applet时代 |
成长 | JDK 1.2-1.4 | 集合框架、NIO、JIT编译器 |
革命 | JDK 5 | 泛型、注解、for-each、自动装箱 |
企业 | JDK 6-7 | 企业级特性,性能优化 |
现代 | JDK 8 | Lambda、Stream、函数式编程 |
模块化 | JDK 9-11 | 模块系统、HttpClient、var |
成熟 | JDK 12-17 | Switch表达式、Records、密封类 |
并发 | JDK 18-21 | 虚拟线程、结构化并发 |
一句话概括:Java从1996年走到今天,每个版本都在进步,JDK 8是转折点,JDK 21是新高点,学Java不懂历史,就像看剧不从头看一样,总会缺了点什么。
好了,Java 这 30 年的家族史咱们今天就盘到这里。从 1996 年的青涩诞生,到 JDK 8 的如日中天,再到 JDK 21 的自我革新,Java 始终在解决开发者痛点的路上不断进化。
有人说技术迭代太快,学了也用不上。但我觉得,了解历史不是为了背版本号、记特性列表,而是为了理解技术的演进逻辑——每一个新特性的出现,都是为了解决过去某个让人抓狂的难题。
Java能走过30年,靠的不是追风口、炒概念,而是一步一个脚印地解决实际问题:
学Java也是一样,不是为了学而学,而是为了解决问题。
希望这篇文章能帮你理清 Java 版本的脉络,以后无论是面试还是做技术选型,心里都能更有底气。
如果你在学 Java 的过程中还遇到过其他奇葩的版本问题,或者觉得文章有哪里讲得不对、不清楚的地方,欢迎在评论区留言交流! 你们的每一个问题,都是我下一篇笔记的灵感来源。如果觉得有用,也别忘了点个赞、收个藏,让更多的小伙伴看到。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。