Java 25 升级后怎样检查预览特性开关
来源:17golang原创
时间:2026-11-03 11:03:09 439浏览 收藏
Java 25 升级后,预览特性的检查重点不是“版本号有没有变成 25”,而是编译阶段和运行阶段是否都使用了同一套预览开关。实际排查可以压缩成 3 个基线检查点、2 个开关阶段和 4 格结果矩阵:先看 java 与 javac,再看 javac 是否带 --enable-preview,最后看 java 启动时是否再次带上它。
官方地址:https://docs.oracle.com/en/java/javase/25/
只要代码依赖 Java 25 的预览特性,javac需要把--enable-preview与--release 25(或匹配的--source)一起使用;生成的 class 启动时还要让java再次看到--enable-preview。少任意一段,升级检查都不能算完成。
一、先把升级后的基线记录成三个检查点
我在迁移时不会直接改构建脚本,而是先把版本基线留下来。原因很简单:终端里的 java 可能已经切到 25,但 javac 仍然来自旧 JDK;也可能本地是 25,CI 的启动器还是另一个版本。基线至少包含运行时、编译器和预览能力提示三个检查点。
# 检查运行时版本,确认启动应用的 java 已切换 java -version # 检查编译器版本,避免 javac 仍来自旧 JDK javac --version # 查看编译器是否提供预览开关,输出只作为能力线索 javac --help-extra | grep -- --enable-preview
这里的数字不是性能指标,而是迁移证据:3 个检查点全部有记录,后面的编译和运行结果才有可比性。如果 java、javac 的主版本不一致,先修复 JDK 路径或 CI 镜像,再判断预览开关。
二、先区分“预览特性”和“已经转正的特性”
Java 25 并不是所有新增语言能力都需要开关。Oracle 的 Java SE 25 语言变更表把 Module Import Declarations、Compact Source Files and Instance main Methods、Flexible Constructor Bodies列为永久特性;仍处于预览状态的是 JEP 507“Primitive Types in Patterns, instanceof, and switch”第三次预览。
| 检查对象 | Java 25 状态 | 是否检查 --enable-preview |
|---|---|---|
| Primitive Types in Patterns、instanceof、switch | 预览语言特性 | 编译和运行都需要 |
| Module Import Declarations | 永久特性 | 不因它单独开启 |
| Flexible Constructor Bodies | 永久特性 | 不因它单独开启 |
| 预览 API | 按对应 API 文档判断 | 编译和运行按契约处理 |
这一步能避免一个常见误判:看到 Java 25 有新语法,就把整个项目标成 preview。正确做法是先按官方变更表确认特性状态,再让构建脚本只为确实使用预览能力的模块开启开关。
三、编译检查:--enable-preview 必须和 release 绑定
javac 文档明确说明,--enable-preview 要和 --release 或 --source 配合使用。对 Java 25 的预览代码,优先把目标版本写成 --release 25,这样源语言、目标 class 和对应 API 版本在同一个契约里。
# 编译 Java 25 预览代码,版本和预览开关必须同时出现 javac --release 25 --enable-preview -d out src/PreviewSample.java # 多文件项目也沿用同一组编译参数,避免模块之间状态不一致 javac --release 25 --enable-preview -d out src/*.java
如果只写 --enable-preview 而没有 --release 或 --source,命令本身就不符合编译器的参数契约;如果把 --release 写成旧版本,则预览能力对应的语言和 API 范围也会错位。

四、运行检查:JVM 启动阶段也要再次开启预览
编译成功只说明 javac 接受了预览语法,不代表 JVM 会加载这些 class。运行时需要再给 java 一次 --enable-preview,这是第二个独立检查点。
# 运行刚才生成的 class,JVM 也必须显式启用预览 java --enable-preview -cp out PreviewSample # 如果交付的是 JAR,把开关放在 -jar 之前 java --enable-preview -jar build/app.jar
只编译时开启、启动时遗漏,常见结果是 JVM 在加载 class 时提示预览特性未启用。这个错误发生在运行入口,不应被误判成业务逻辑异常;检查启动脚本、容器参数和 IDE 的 Run Configuration 是否把同一开关传给了 JVM。
如果使用的是 Java 25 预览的 primitive pattern,可以把示例代码替换成项目中的真实最小样例。重点不是样例复杂度,而是让同一个 class 经过“带开关编译”和“带开关启动”两次明确检查。
五、用四格检查矩阵定位升级遗漏
迁移时最省时间的方法,是把“编译开关”和“运行开关”拆成两列,不要用一次成功的本地命令代替整个判断。下面四格覆盖了最常见的升级结果:
| 预览源代码 | 编译阶段 | 运行阶段 | 结论 |
|---|---|---|---|
| 否 | 不需要 preview | 不需要 preview | 普通 Java 25 代码 |
| 是 | 有 --release 25 --enable-preview | 有 --enable-preview | 完整链路 |
| 是 | 缺编译开关 | 有运行开关 | 编译阶段先失败 |
| 是 | 编译成功 | 缺运行开关 | 加载 class 时失败 |
这张表给出的结果是可复现的判断逻辑,不是我替读者虚构的运行日志。把四格写进 CI 或迁移清单后,升级问题会从“Java 25 不兼容”收敛成“哪一个阶段缺了开关”。

六、把检查结果固化到构建和启动脚本
如果只有开发者本地命令带开关,下一次发布仍然会丢。建议把 Java 25 的版本和 preview 参数放在同一个构建 profile 或脚本变量里,并让编译与启动分别显式引用。
# 在 CI 中集中声明版本,避免编译器和启动器各写一套 JAVA_RELEASE=25 PREVIEW_FLAG=--enable-preview # 编译阶段绑定 release 与 preview javac --release "$JAVA_RELEASE" "$PREVIEW_FLAG" -d out src/PreviewSample.java # 运行阶段再次传递 preview,不能复用编译阶段的隐式状态 java "$PREVIEW_FLAG" -cp out PreviewSample
正式环境是否使用预览能力,要由项目的兼容性策略决定。预览特性仍可能在后续版本中调整或撤回,升级时必须重新阅读对应版本文档、重新编译,不能把旧版本生成的预览 class 当作跨版本构件长期复用。
七、常见问题
只执行 java -version 能确认预览开关吗?
不能。它只能说明当前调用到的运行时版本,不能证明编译器参数、class 文件来源和启动参数都正确。至少还要记录 javac --version、编译命令和运行命令。
Java 25 的永久特性还要加 --enable-preview 吗?
不需要因为“它是 Java 25 新特性”就自动开启。先按官方语言变更表判断;已经转正的特性按普通 Java 25 源码编译,只有真正使用预览语言或预览 API 时才按对应契约处理。
本地能跑,CI 却提示 preview 未启用怎么办?
按四格矩阵分别检查 CI 的 javac、构建参数、java 启动参数和容器入口。最常见的差异是构建插件接收了 --enable-preview,但测试任务或生产启动命令没有接收。
总结
Java 25 升级后的预览开关检查可以固定成一条短路径:先记录 3 个版本/能力基线,再确认目标特性是不是预览,之后在编译阶段用 --release 25 --enable-preview,在运行阶段再次使用 --enable-preview,最后用 4 格矩阵定位遗漏。这样检查的对象是开关所在的阶段,结论才不会停留在“版本已经升级”的表面。
参考资料:
https://docs.oracle.com/en/java/javase/25/language/java-language-changes-summary.htmlhttps://docs.oracle.com/en/java/javase/25/migrate/significant-changes-jdk-25.htmlhttps://docs.oracle.com/en/java/javase/25/docs/specs/man/javac.htmlhttps://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html
-
Golang · Go教程 | 2个月前 | 标准库 · JSON · go · 后端开发 · 版本迁移 · JSON Go 1.27 encoding/json/v2 encoding/json/jsontext GOEXPERIMENT195 收藏
-
366 收藏
-
141 收藏
-
431 收藏
-
347 收藏
-
103 收藏
-
305 收藏
-
159 收藏
-
257 收藏
-
176 收藏
-
388 收藏
-
280 收藏
-
218 收藏
-
439 收藏
-
461 收藏
-
105 收藏
-
468 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习