Java 11 新特性详解:像运行 Python 一样运行 Java(JEP 330)
引言:从两步到一步
在 Java 11 之前,运行任何一个 Java 程序——哪怕是最简单的 “Hello World”——都必须经历一个固定的两步流程:
1 | $ javac HelloWorld.java # 第一步:编译生成 HelloWorld.class |
这种流程对于大型项目而言是严谨且必要的,但对于初学者练手、快速验证代码片段或编写小型工具脚本来说,却显得有些繁琐,且每次修改后都必须重新编译,否则运行的仍是旧版本的字节码。
从 Java 11 开始,这一流程得到了极大的简化。现在,你可以跳过显式的 javac 编译步骤,直接使用 java 命令运行源代码文件。
功能初探:一行命令搞定一切
使用方法
新用法非常简单。假设你有一个 HelloWorld.java 文件,内容如下:
1 | public class HelloWorld { |
在命令行中,直接输入以下命令即可运行:
1 | $ java HelloWorld.java |
终端将直接输出 Hello Java 11!。
工作原理:内存中的“隐形”编译
这一功能是 Java 11 引入的 JEP 330: Launch Single-File Source-Code Programs 的核心内容。其原理是:当 java 启动器检测到目标是 .java 源文件时,它会在后台自动调用编译器(javac),将源代码编译为字节码。与传统编译不同的是,这些字节码文件(.class)并不会被写入磁盘,而是全部存储在内存中。编译完成后,JVM 会立即从内存中加载并执行这个类。
也就是说,java HelloWorld.java 在效果上近似于 javac -d <memory> HelloWorld.java && java -cp <memory> HelloWorld,整个过程对用户完全透明。
参数传递
向程序传递命令行参数的方式与传统方式完全一致。参数直接写在源文件名之后即可:
1 | $ java HelloWorld.java Java 11 |
上面的代码中,args[0] 的值为 Java,args[1] 的值为 11。
宽松的文件名规则
一个有趣的点是,该功能对文件名与公共类名的匹配要求较为宽松。例如,将文件重命名为 WrongName.java(内容不变),依然可以直接运行:
1 | $ java WrongName.java |
程序会正常执行。但这仅限 java 命令;若改用 javac 编译该文件,则会因类名与文件名不符而报错。当然,尽管可以运行,始终建议遵循标准的命名规范(文件名与 public class 名一致),以保持代码的可维护性。

进阶选项:命令行与 Shebang 脚本
源文件模式的触发条件
java 命令进入“源文件模式”有两个触发条件,满足其一即可:
- 文件名后缀:命令行第一个参数(JVM 选项之后)是一个以
.java结尾的文件名。 --source参数:命令行中显式指定了--source版本号。
使用 --class-path 选项
你仍然可以在运行源文件时指定类路径(--class-path 或 -cp),选项需要放在源文件名之前:
1 | $ java --class-path=/some/path HelloWorld.java |
Shebang 支持:像脚本一样运行 Java
Java 11 还支持将 Java 程序作为 Shebang 脚本运行,进一步模糊了编译型语言与脚本语言之间的界限。在 Unix/Linux/macOS 系统上,你可以创建一个没有 .java 扩展名的文件,并在第一行添加 Shebang(#!)指令,指向 Java 启动器的路径并指定 --source 版本。
示例: 创建一个名为 add 的文件,内容如下:
1 |
|
赋予可执行权限后,即可像普通脚本一样调用:
1 | $ chmod +x add |
注意:Shebang 功能需要
--source参数支持,且文件不能使用.java扩展名,否则 Shebang 行会被视为非法字符而导致错误。该功能在 Windows 上不直接支持。
限制与适用场景
这项功能虽便捷,但存在明确的限制,了解这些限制有助于避免踩坑。
核心限制:单文件
在 Java 11 中,此功能仅适用于单个源文件。程序所依赖的其他类必须定义在同一个 .java 文件中,不能引用其他源文件或第三方 JAR 包。例如,如果 Student.java 引用了 Teacher.java 中的 Teacher 类,运行时将报错“找不到符号”。
类路径冲突
如果当前目录下同时存在同名的源文件(如 HelloWorld.java)和编译后的字节码文件(如 HelloWorld.class),再使用 java HelloWorld.java 运行时会报错:error: class found on application class path。这是为了防止类路径冲突导致的行为不一致。
适用场景
- Java 初学者练手:省去了编译步骤,降低入门门槛。
- 快速原型验证与探索性编程:快速测试某个 API 或代码片段,无需建立完整项目。
- 编写小型实用工具或脚本:在熟悉 Java 生态的情况下,替代部分 Shell/Python 脚本。
- 不适合:大型项目、需要外部依赖(JAR 包)、涉及多模块的项目开发。
未来演进:多文件支持
Java 22 进一步增强了此功能。通过 JEP 458: Launch Multi-File Source-Code Programs,java 启动器现在可以自动定位、编译并加载多个源文件,前提是源文件的目录结构与其包结构相匹配。这意味着你可以在不借助构建工具的情况下,直接运行由多个源文件组成的简单程序,进一步拓宽了“免编译运行”的使用场景。
总结
Java 11 引入的“直接运行源文件”功能,是一项旨在提升开发体验的务实改进。它通过将编译步骤隐藏在内存中,将开发者从繁琐的两步操作中解放出来,尤其适合快速迭代和轻量级编程场景。不过,它并非要取代传统的 javac + java 流程,而是在特定场景下提供一个更轻便、更高效的替代方案。掌握这一特性,能让你的 Java 日常开发与学习更加游刃有余。

