版本分类
1. 版本分类与发布周期
LTS 版本:每 2 年发布一次,提供长期维护和安全更新支持,是企业级应用的首选。截至 2025 年 7 月 24 日,最新 LTS 版本为JDK 21(2023 年 9 月发布),历史重要 LTS 版本包括 JDK 8、11、17。
非 LTS 版本:每 6 个月发布一次,包含最新特性但支持周期短(通常仅 6 个月),适合追求新功能的开发者或测试场景。截至 2025 年 7 月 24 日,最新非 LTS 版本为JDK 24。
2.各版本发布与停止支持时间(部分关键版本)
|
GA 版本 |
发布日期 |
停止支持日期(EOSL) |
版本类型 |
|
JDK 8 LTS |
2014 年 03 月 18 日 |
2030 年 12 月 |
LTS |
|
JDK 9 |
2017 年 09 月 21 日 |
2018 年 03 月 |
非 LTS |
|
JDK 11 LTS |
2018 年 09 月 25 日 |
2026 年 09 月 |
LTS |
|
JDK 17 LTS |
2021 年 09 月 14 日 |
2029 年 09 月 |
LTS |
|
JDK 21 LTS |
2023 年 09 月 19 日 |
2031 年 09 月 |
LTS |
|
JDK 24 |
2025 年(推测) |
2025 年(推测,6 个月后) |
非 LTS |
3.2024 年 JDK 用户占比
JDK 17:35%
JDK 11:33%
JDK 8:29%
其他版本(如 JDK 21 等):3%
现状:尽管新版本不断推出,JDK 8 仍被多数企业采用,但 JDK 17、11 的占比正逐步提升。
JEP
1. JEP 定义
JEP(JDK Enhancement Proposals)即 JDK 增强提案,是 Java 平台新功能或重大改进的 “提案说明书”,涵盖功能描述、设计思路、实现方式、影响范围及与现有 Java 生态的关系等内容。
2.JEP 分类及示例
|
JEP 类型 |
示例 |
适用人群 / 场景 |
|
语言特性 |
switch 表达式、模式匹配、Record 类 |
所有 Java 开发者,日常编码高频使用 |
|
JVM 改进 |
ZGC、Shenandoah、分段编译 |
JVM 工程师、性能调优人员 |
|
API 增强 |
Stream、Collectors、集合增强 |
所有 Java 开发者,提升编码效率 |
|
工具改进 |
jshell、jpackage、jfr |
开发 / 测试人员,辅助开发测试 |
|
架构调整 |
模块化系统(JPMS)、孵化器模块 |
架构师、大型项目开发团队 |
3.学习原则
无需学习所有 JEP:部分 JEP 属于底层优化(如 JVM 垃圾回收改进)或实验性内容,与多数开发者日常工作无关。
重点学习方向:聚焦与工作相关的 API 增强、语言特性类 JEP;关注已稳定、可用于生产环境的 JEP,避免依赖实验性 JEP。
各版本核心新特性
1. JDK 9 新特性
(1)JPMS 模块化(Project Jigsaw)
背景:解决传统 JAR 方式的臃肿、内部 API 暴露、依赖复杂等问题(如 rt.jar 全量加载导致性能负载)。
核心优势:
性能提升:仅加载运行所需模块,加快启动速度。
增强封装:通过exports指令控制对外暴露的包,隐藏内部实现。
提升安全性:减少潜在攻击面。
关键指令:
requires:声明当前模块依赖的其他模块(如requires ModuleA;)。
exports:声明当前模块对外暴露的包(如exports com.briup.utils;),支持exports ... to ...指定暴露对象。
requires transitive:实现依赖传递(如requires transitive java.sql;)。
open/opens:解决反射访问私有包的问题(如open module ModuleA;)。
注意事项:module-info.java必须放在 src 目录下;依赖模块包名不可重复。
(2)交互式编程(JShell)
定义:Java 的 REPL(Read-Eval-Print Loop)环境,支持直接输入代码片段并即时查看结果,无需编写完整类 / 方法。
基础功能:执行表达式(如2 + 3)、定义变量 / 方法 / 类、查看定义内容(/vars//methods//types)、保存 / 加载代码(/save//open)。
(3)其他重要特性
接口私有方法--> 支持普通私有方法和静态私有方法,增强接口封装性,减少代码重复(如抽取公共逻辑)
钻石操作符增强--> 匿名类中支持<>,编译器自动推断泛型类型(如Comparator<>())
资源释放优化--> try-with-resources 支持已定义的资源对象(如try (fis; fos) {...})
String 底层改进--> 由char[]改为byte[] + coder,纯 ASCII 字符串内存消耗减少一半
集合 of 方法--> 静态工厂方法List.of()/Set.of()/Map.of(),快速创建不可变集合
Stream API 新增方法--> 新增takeWhile(保留满足条件元素至不满足)、dropWhile(跳过满足条件元素)等 4 个方法
2. JDK 10 新特性
(1)局部变量类型推断
核心功能:用var关键字声明局部变量,编译器根据初始化表达式自动推断类型(如var name = "Tom";推断为 String)。
适用场景:局部变量声明(如循环变量、集合遍历变量)、简化复杂泛型声明(如var entrySet = map.entrySet();)。
限制场景:不可用于成员变量、方法参数、方法返回值;变量必须初始化;不可用于数组静态初始化(如var arr = {1,2,3}错误)。
(2)新增 API
集合copyOf()--> List.copyOf()/Set.copyOf()/Map.copyOf(),创建不可变集合副本
IO 流transferTo()--> InputStream/Reader 的该方法可直接将数据传输到输出流,简化文件拷贝
Charset 参数构造函数--> InputStreamReader/OutputStreamWriter 支持指定 Charset(如StandardCharsets.UTF_8)
ByteArrayOutputStreamtoString(Charset)--> 按指定字符集将缓冲区内容转为字符串,避免编码问题
3. JDK 11 新特性(LTS 版本)
(1)String 新增方法
|
方法名 |
功能描述 |
示例 |
|
isBlank() |
判断字符串是否为空白(含空格、制表符、换行符) |
" \t \n ".isBlank() → true |
|
strip() |
移除首尾所有空格(含 Unicode 空格),区别于trim()(仅处理 ASCII 空格) |
" Hello ".strip() → "Hello" |
|
repeat(int n) |
将字符串重复 n 次 |
"Java".repeat(3) → "JavaJavaJava" |
|
lines() |
将字符串按行分割为 Stream,用于统计行数或处理每行内容 |
"A\nB\nC".lines().count() → 3 |
(2)HTTP Client(标准 API)
替代对象:取代旧的HttpURLConnection API。
核心优势:支持同步 / 异步请求、HTTP/2 协议、WebSocket;API 更简洁,减少样板代码。
示例:同步请求通过client.send(),异步请求通过client.sendAsync()返回CompletableFuture。
(3)局部类型推断改进
支持在 lambda 表达式形参中使用var,并可添加注解(如(@NotNull var text) -> {...}),提升代码清晰度与静态分析能力。
4. JDK 12 - 17 新特性
(1)switch 表达式增强
JDK 12(预览):支持多 case 合并(如case 12, 1, 2 -> "冬季"),无需break,直接返回值。
JDK 13(预览):新增yield语句,支持在代码块中返回值(如case 6,7,8 -> { yield "夏季"; })。
JDK 14(正式):成为标准特性,彻底替代传统 switch 的冗长写法。
(2)文本块(Text Blocks)
JDK 13(预览)- JDK 15(正式):用"""界定多行字符串,无需\n或+拼接,自动调整缩进(如 HTML/XML/SQL 语句编写)。
示例:
String html = """
<html>
<body>
<p>Hello</p>
</body>
</html>
""";
(3)instanceof 模式匹配
JDK 16(正式):instanceof检查通过后自动完成类型转换,减少显式转换代码(如if (obj instanceof String str) { str.length(); })。
JDK 17 + 扩展:支持在 switch 中使用(如case Circle c -> System.out.println(c.radius());)。
(4)Record 类
JDK 16(正式):不可变数据载体类,自动生成全参构造、equals()/hashCode()/toString()、属性 getter(如Person(String name, int age)自动生成name()/age())。
限制:类默认 final,不可继承;属性默认 final,无 setter;不可定义实例字段(可定义静态字段 / 方法)。
(5)密封类(Sealed Classes)
JDK 17(正式):用sealed关键字定义,指定允许继承 / 实现的子类 / 实现类(如sealed interface Shape permits Circle, Rectangle),控制类层次结构。
子类约束:子类需为final(不可继承)、sealed(继续限制)或non-sealed(取消限制,可自由继承)。
关键问题
问题 1:企业在选择 JDK 版本时,应优先考虑 LTS 版本还是非 LTS 版本?依据是什么?
答案:
企业应优先选择 LTS 版本,依据如下:
支持周期:LTS 版本支持周期极长(如 JDK 8 支持至 2030 年、JDK 17 支持至 2029 年),能为企业级应用提供长期的安全更新和维护,避免频繁升级版本带来的成本;非 LTS 版本仅支持 6 个月,需快速跟进新版本,稳定性和维护性不足。
生态兼容性:多数企业级框架(如 Spring Boot、MyBatis)会优先适配 LTS 版本,确保功能稳定运行;非 LTS 版本的新特性可能未被框架完全兼容,存在潜在风险。
用户基础:2024 年数据显示,JDK 8(35%)、11(33%)、17(29%)三大 LTS 版本占据 97% 的用户市场,社区资源丰富,遇到问题时易获取解决方案;非 LTS 版本用户占比低,问题排查难度更高。
例外场景:若企业需验证某非 LTS 版本的特定新特性(如 JDK 20 的某实验性 API),可在测试环境使用,但生产环境仍需回归 LTS 版本。
问题 2:JDK 9 的 JPMS 模块化解决了传统 JAR 包方式的哪些核心问题?实际开发中配置模块化需注意哪些关键点?
答案:
1. JPMS 模块化解决的传统 JAR 包核心问题
环境臃肿与性能问题:传统 JAR 包需全量加载(如 rt.jar),即使应用仅用部分类,也会增加 JVM 内存负载和启动时间;模块化支持 “按需加载”,仅加载运行所需模块,提升性能。
内部 API 暴露问题:传统方式依赖权限修饰符(public/private)封装,无法隐藏整个包,内部实现易被外部访问 / 修改;模块化通过exports指令精确控制暴露的包,未导出包完全隐藏。
依赖管理复杂问题:大型项目中 JAR 包依赖易出现版本冲突、重复依赖;模块化通过requires指令明确依赖关系,减少依赖混乱。
安全性问题:传统方式难以控制库的访问权限,可能因内部 API 被滥用导致安全漏洞;模块化限制包可见性,减少潜在攻击面。
2. 实际开发配置模块化的关键点
配置文件位置:module-info.java必须放在模块的 src 目录根路径下,否则 JVM 无法识别模块结构。
包名唯一性:依赖模块与被依赖模块的包名不可重复(如 ModuleA 和 ModuleB 均含com.briup.test包,会导致运行报错)。
依赖传递控制:若需让依赖模块的依赖对当前模块可见,需用requires transitive(如requires transitive java.sql;),普通requires无法实现依赖传递。
反射访问处理:若外部模块需通过反射访问当前模块的私有包,需用open(开放整个模块)或opens(开放指定包)指令(如opens com.briup.model to ModuleB;)。
编译版本适配:模块化仅支持 JDK 9 及以上版本,需确保项目编译版本设置为-source 9或更高(如 IDEA 中配置 “Project bytecode version” 为 9+)。
问题 3:JDK 8 到 JDK 17 的 String 类有哪些重要改进?这些改进对实际开发有哪些影响?
答案:
1. JDK 8 到 JDK 17 String 类的重要改进
JDK 9底层存储结构优化--> 由private final char[] value改为private final byte[] value + private final byte coder,coder标识编码(1 字节 / 2 字节)
JDK 11新增实用方法--> 新增isBlank()、strip()、stripLeading()、stripTrailing()、repeat(int)、lines()6 个方法
2. 改进对实际开发的影响
JDK 9 底层优化的影响:
内存节省:对于纯 ASCII 字符串(如英文、数字),存储由 2 字节 / 字符降至 1 字节 / 字符,内存消耗减少 50%,尤其适合处理大量文本数据的应用(如日志系统、文本解析工具),能显著降低 JVM 内存占用。
性能平衡:虽字符访问时需通过coder判断编码,增加轻微性能开销,但因内存占用减少,缓存命中率提升,大型应用的整体执行速度通常会提高。
兼容性保障:底层结构变化完全透明,上层 API(如length()、charAt())无任何改变,现有 String 相关代码无需修改即可兼容 JDK 9+。
JDK 11 新增方法的影响:
简化字符串操作:减少样板代码,如判断空白字符串无需再写str.trim().isEmpty(),直接用str.isBlank();重复字符串无需循环拼接,用str.repeat(n)即可。
处理多语言空格:strip()系列方法支持 Unicode 空格(如中文全角空格),trim()仅处理 ASCII 空格,避免因多语言空格导致的逻辑错误(如用户输入含全角空格时,trim()无法识别)。
便捷文本处理:lines()方法将字符串按行分割为 Stream,便于处理多行文本(如统计日志行数、按行过滤内容),结合 Stream API 可简化代码(如str.lines().filter(line -> line.contains("error")).count()统计错误日志行数)。
提升代码可读性:新增方法语义更清晰(如repeat(3)比循环拼接更易理解),降低代码维护成本。
3167

被折叠的 条评论
为什么被折叠?



