Java 脚本化:现代自动化任务的新选择
目录
脚本编写的困境
作为一名 Java 开发人员,你是否和我一样,总是记不住 Bash 或 Python 的语法来编写简单的脚本?
你最终只能靠“凭感觉编码”(vibe coding),然后在需要修改时又陷入困境。要是能用 Java 来写该多好!
你可能会说:“Java 不适合写脚本”,或者“我不想用 Maven 或 Gradle”。现代 Java 已经悄然消除了那些使其不适合脚本编写的传统障碍。凭借即时执行、Shebang 支持和零配置自动化,Java 已经演变成一种精简的脚本语言。你可以编写精确、可维护的代码,而无需使用不熟悉的语言进行“凭感觉编码”。
在本文中,我将向你展示 Java 如何成为一流的脚本语言。它或许会成为你新的自动化工具首选。
告别手动编译
如果你想编写 Java 脚本,面临的第一个问题就是编译。对于一个简单的脚本,你可能不想运行 javac 并管理 .class 文件。但自 Java 11 起(通过 JEP 330),你可以通过 java 启动器直接运行源代码程序。
单文件执行
假设你想用 Java 重写 ls 命令,你可以这样做:
如果你想运行它,无需 javac,直接执行:
无需 javac,也没有 .class 文件堆积在你的目录中。只需即时执行。
多文件支持
自 Java 22 起(通过 JEP 458),你不再局限于单文件程序。现在你可以编写多文件程序并直接运行。Java 启动器会自动定位并编译子目录中相关的源文件。例如:
这只是一个过于复杂的“Hello World!”示例,但它展示了多文件程序可以被直接运行:
该功能对于需要多个类的复杂脚本特别有用,也非常适合不想处理项目配置的学习者。
在底层,启动器会自动调用编译器并将编译结果存储在内存中。没有构建工具的冗余,没有中间文件,只有纯粹的执行。就脚本编写而言,Java 现在感觉和 Python 或 Ruby 一样即时。
为何如此繁琐?
好的脚本语言的一个关键点是消除样板代码。老实说,Java 有时确实显得有些冗长。最臭名昭著的例子就是 public static void main(String[] args) 签名。如果你只是想写个简单的脚本,这些代码大多毫无意义。打印“Hello World!”至少需要 5 行代码,其中大部分都是样板。
Java 的演进
Java 25 在 Java 21 和 22 的预览版基础上,引入了多项直接解决冗余问题的特性。
紧凑源文件 (Compact Source Files) 和 实例 main 方法 (Instance Main Methods) 消除了对样板签名的需求。
- 紧凑源文件:可以在顶层直接编写方法和字段,无需类声明。
- 实例 main 方法:将
public static void main(String[] args)简化为void main()。
有了这些特性,“Hello World”可以变得如此简单:
JVM 会自动选择入口点,优先使用实例 main() 方法。这使得你的脚本看起来更自然,不再像传统的企业级 Java 代码。
更简单的控制台交互
过去,与控制台交互有些麻烦。首先,每次想打印内容都要输入 System.out.println("...")。当需要读取输入时,情况更糟,你不得不使用 BufferedReader 或 Scanner。于是代码很快变成了这样:
得益于“紧凑源文件”,现在你可以使用 IO 类:
IO 类位于 java.lang 包中,因此每个源文件都会隐式导入它。
如果你想了解更多信息,建议阅读 JEP 512。
Java 原生脚本:Shebang 支持
任何脚本语言的一个定义性特征是能够像 ./myscript 那样直接运行,而无需显式调用解释器。许多脚本语言通过“Shebang”行 (#!) 来实现这一点。文件开头的这一行会告诉操作系统使用哪个程序来运行它。
自 Java 11(通过 JEP 330)起,java 启动器支持此约定。
让我们使用上述现代 Java 特性,将之前的 ListFiles 示例重构为一个可执行脚本:
保存文件(例如命名为 ls,无需 .java 后缀)并使其可执行:
你的 Java 代码现在就是一个一流的 CLI 命令,与 Bash 或 Python 脚本别无二致。
可移植性提示:将脚本移动到 PATH 中的目录,例如 /usr/local/bin/:
突然间,Java 感觉就像一门原生的脚本语言。
使用 JBang 进行高级自动化
这些内置特性使 Java 成为了一门有能力的脚本语言。但 JBang 通过消除设置开销并启用高级功能,将其提升到了一个新的水平。
什么是 JBang?
JBang 让你能够以前所未有的简便方式创建、编辑和运行独立的 Java 程序。有了 JBang,你的脚本可以自动获取依赖,无需深入研究 Maven 或 Gradle。它可以在任何平台(包括 Docker 和 Github Actions)上运行。最棒的是,如果缺失所需的 Java 版本,JBang 会自动下载。
你还可以使用 JBang 运行任何 JAR 文件,无论是本地还是在线(通过 Maven Central)。
运行 JBang 脚本非常简单:
依赖管理
这是 JBang 真正大放异彩的地方。使用特殊的注释在文件中直接声明依赖,无需 Maven 或 Gradle。
注意 /// 开头的 Shebang 行,这是 JBang 特有的,允许脚本直接执行。
JBang 会自动下载并管理这些依赖。无需 Maven,无需 Gradle,只需声明并使用即可。
强大的功能
JBang 提供了许多高级功能:
IDE 集成:JBang 可以安装 VSCodium,生成项目结构,并在你的 IDE 中打开脚本:
原生二进制文件:它支持使用 GraalVM 生成原生镜像二进制文件,以实现近乎即时的启动:
使用原生镜像时要小心,特别是在反射方面。更多信息请参阅此处。
模板:JBang 提供了一套模板,帮助你快速启动脚本。
提升脚本能力:使用 Picocli 实现丰富的 CLI
简单的脚本是一个很好的起点。然而,为了获得健壮的 CLI 体验,你通常需要选项、位置参数和帮助菜单。这时 Picocli 就派上用场了。
专业级工具
Picocli 与 JBang 完美集成,可实现带 ANSI 颜色的帮助消息和强类型参数解析。构建具有自动生成帮助、版本信息、类型检查和美观错误消息的专业 CLI。
运行它:
零代码 CLI 体验
Picocli 处理了以下复杂性:
- 使用
--help自动生成帮助 - 使用
--version显示版本 - 类型转换和验证
- 用于提高可读性的 ANSI 颜色
- 子命令和命令层级
你的脚本现在可以媲美专业构建的 CLI 工具了。## Java 的新纪元
我希望你现在已经明白,Java 不仅仅代表着企业级的复杂性和冗长的样板代码。你可以轻松地利用它构建强大的自动化脚本。
为什么这很重要
可维护性:Java 脚本提供了 Bash 往往缺乏的类型系统和结构。六个月后,强类型和 IDE 的支持会让理解和修改代码变得更加容易。
熟悉感:你已经掌握了 Java。既然你可以利用现有的专业知识,为什么还要为了自动化而切换到另一种语言呢?
强大功能:整个 Java 生态系统触手可及。数以百万计的库和经过实战检验的框架,都可以集成在简单的脚本中。
性能表现:GraalVM 原生镜像(Native Images)让你的脚本能够编译成具有即时启动速度的原生二进制文件,足以与 Go 或 Rust 媲美。
总结
得益于 Shebang 支持、JBang 以及实例 main 方法,Java 现在已成为一台精简的自动化机器。繁文缛节已成过去,阻碍已被消除。剩下的就是一个功能强大、类型安全、易于维护的脚本语言,而它恰好就是 Java。
下次当你需要编写快速自动化脚本时,不要再习惯性地去用 Bash 或 Python。尝试一下 Java,你可能会惊讶于它的体验是多么出色。IDE 为你提供助力,类型检查在运行时之前就能捕获 Bug,而精准性取代了“凭感觉编程”(vibe coding)。
Java 脚本并非遥不可及的未来,它已经到来,而且表现非凡。
本文转自 JavaScript (No, Not That One): Modern Automation with Java,发布于 foojay。