1. 引言
Kotlin 是一门运行在 JVM 上的现代编程语言,语法简洁、类型安全,并且与 Java 高度互操作。虽然大多数开发者习惯使用 IntelliJ IDEA 或 Android Studio 进行开发,但在某些场景下,比如 CI/CD 流水线、轻量级脚本、服务器环境或教学演示中,使用命令行直接编译 Kotlin 代码反而更加高效和灵活。本文将系统介绍如何使用命令行编译 Kotlin 程序,涵盖环境准备、基础编译、依赖管理、打包运行等完整流程,并配有丰富的代码实例。
2. 环境准备
在开始命令行编译之前,需要先安装 Kotlin 编译器。Kotlin 官方提供了多种安装方式,这里介绍最常用的几种。
2.1 安装 JDK
Kotlin 运行在 JVM 之上,因此首先需要安装 JDK(Java Development Kit)。推荐使用 JDK 8 或更高版本。可以通过以下命令验证 JDK 是否安装成功:
java -version javac -version如果输出类似下面的信息,说明 JDK 已正确安装:
openjdk version "17.0.8" 2023-07-18 OpenJDK Runtime Environment (build 17.0.8+7) OpenJDK 64-Bit Server VM (build 17.0.8+7, mixed mode, sharing)2.2 安装 Kotlin 编译器
Kotlin 编译器可以通过多种方式安装,这里介绍三种主流方式。
方式一:使用 SDKMAN(推荐)
SDKMAN 是 JVM 生态中非常流行的版本管理工具,可以方便地安装和切换 Kotlin 版本:
curl -s "https://get.sdkman.io" | bash source "$HOME/.sdkman/bin/sdkman-init.sh" sdk install kotlin方式二:使用 Homebrew(macOS)
brew install kotlin方式三:直接下载二进制发行版
可以从 Kotlin 官方 GitHub Releases 页面下载最新的编译器压缩包,解压后将bin目录添加到系统PATH环境变量中。
安装完成后,验证 Kotlin 编译器是否可用:
kotlinc -version如果输出类似下面的信息,说明 Kotlin 编译器已安装成功:
info: kotlinc-jvm 1.9.22 (JRE 17.0.8+7)3. 第一个 Kotlin 程序
环境准备好之后,我们来编写并编译第一个 Kotlin 程序。
3.1 编写源代码
创建一个名为Hello.kt的文件,内容如下:
fun main() { println("Hello, Kotlin!") }3.2 编译为字节码
使用kotlinc命令将 Kotlin 源码编译为 JVM 字节码:
kotlinc Hello.kt -include-runtime -d hello.jar参数说明:
-include-runtime:将 Kotlin 运行时库一并打包进生成的 jar 文件中,这样生成的 jar 可以直接运行。-d:指定输出文件的名称和路径,这里输出为hello.jar。
编译完成后,当前目录下会生成一个hello.jar文件。
3.3 运行程序
使用java -jar命令运行编译好的 jar 包:
java -jar hello.jar输出结果:
Hello, Kotlin!至此,我们已经完成了第一个 Kotlin 程序的命令行编译和运行。
4. 编译多个源文件
实际项目中,代码通常会拆分成多个文件。下面演示如何编译多个 Kotlin 源文件。
4.1 创建多个源文件
创建MathUtils.kt文件:
object MathUtils { fun add(a: Int, b: Int): Int = a + b fun multiply(a: Int, b: Int): Int = a * b }创建Main.kt文件:
fun main() { val sum = MathUtils.add(3, 5) val product = MathUtils.multiply(3, 5) println("Sum: $sum") println("Product: $product") }4.2 编译多个文件
在命令行中同时传入多个源文件进行编译:
kotlinc MathUtils.kt Main.kt -include-runtime -d app.jar运行程序:
java -jar app.jar输出结果:
Sum: 8 Product: 154.3 使用通配符编译目录下所有文件
当源文件较多时,可以使用通配符一次性编译目录下的所有 Kotlin 文件:
kotlinc src/*.kt -include-runtime -d app.jar这种方式要求所有源文件都位于src目录下。
5. 编译为 class 文件
除了打包成可执行的 jar 文件,也可以只编译生成.class字节码文件,便于后续集成到其他构建流程中。
5.1 编译生成 class 文件
不带-include-runtime参数编译时,默认只生成.class文件:
kotlinc Hello.kt -d classes上述命令会在classes目录下生成HelloKt.class文件。注意,Kotlin 文件编译后生成的类名默认是「文件名 + Kt」。
5.2 查看生成的 class 文件
ls classes/输出结果:
HelloKt.class5.3 运行 class 文件
运行 class 文件时需要将 Kotlin 运行时库加入 classpath:
java -cp classes:kotlin-stdlib.jar HelloKt其中kotlin-stdlib.jar是 Kotlin 标准库,通常位于 Kotlin 编译器安装目录的lib文件夹下。如果使用 SDKMAN 安装,可以通过以下命令找到它:
find ~/.sdkman/candidates/kotlin -name "kotlin-stdlib*.jar"6. 使用第三方依赖
实际开发中经常需要引用第三方库。命令行编译时,可以通过-cp参数指定依赖的 jar 文件。
6.1 下载第三方库
以 Gson 库为例,先从 Maven 中央仓库下载gson.jar文件,放到项目的libs目录下。
6.2 编写使用第三方库的代码
创建JsonDemo.kt文件:
import com.google.gson.Gson data class User(val name: String, val age: Int) fun main() { val user = User("Alice", 30) val gson = Gson() val json = gson.toJson(user) println(json) val parsed = gson.fromJson(json, User::class.java) println("Parsed: ${parsed.name}, ${parsed.age}") }6.3 编译并运行
编译时通过-cp指定依赖:
kotlinc JsonDemo.kt -cp libs/gson.jar -include-runtime -d json-demo.jar运行程序:
java -cp json-demo.jar:libs/gson.jar JsonDemoKt输出结果:
{"name":"Alice","age":30} Parsed: Alice, 30注意,运行包含第三方依赖的程序时,需要将依赖 jar 一并加入 classpath。
7. 使用 kotlin 命令直接运行脚本
Kotlin 还支持以脚本方式直接运行.kts文件,无需先编译成字节码,非常适合快速验证代码逻辑。
7.1 创建脚本文件
创建script.kts文件:
fun greet(name: String) = "Hello, $name!" val message = greet("Kotlin Script") println(message) val numbers = listOf(1, 2, 3, 4, 5) val sum = numbers.filter { it % 2 == 0 }.sum() println("Sum of even numbers: $sum")7.2 运行脚本
kotlinc -script script.kts输出结果:
Hello, Kotlin Script! Sum of even numbers: 6脚本模式非常适合编写自动化任务、数据处理脚本等场景。
8. 编译选项详解
掌握常用的编译选项,可以更灵活地控制编译过程。下表列出了kotlinc的常用参数:
| 参数 | 说明 |
|---|---|
-d <path> | 指定输出文件或目录 |
-include-runtime | 将 Kotlin 运行时库打包进 jar |
-cp <path> | 指定 classpath,用于引用第三方依赖 |
-script | 以脚本模式运行.kts文件 |
-nowarn | 不输出警告信息 |
-Werror | 将警告视为错误 |
-jvm-target <version> | 指定目标 JVM 版本,如1.8或17 |
-Xopt-in | 启用实验性 API |
例如,指定 JVM 目标版本进行编译:
kotlinc Hello.kt -jvm-target 1.8 -include-runtime -d hello.jar9. 实战:构建一个命令行计算器
下面通过一个完整的实战项目,综合运用前面介绍的知识,构建一个支持加减乘除的命令行计算器。
9.1 项目结构
calculator/ ├── src/ │ ├── Calculator.kt │ └── Main.kt └── libs/9.2 编写计算器核心逻辑
创建src/Calculator.kt文件:
object Calculator { fun add(a: Double, b: Double): Double = a + b fun subtract(a: Double, b: Double): Double = a - b fun multiply(a: Double, b: Double): Double = a * b fun divide(a: Double, b: Double): Double { require(b != 0.0) { "除数不能为零" } return a / b } }9.3 编写入口程序
创建src/Main.kt文件:
fun main(args: Array<String>) { if (args.size != 3) { println("用法: java -jar calculator.jar <数字1> <操作符> <数字2>") println("示例: java -jar calculator.jar 10 + 5") return } val a = args[0].toDouble() val op = args[1] val b = args[2].toDouble() val result = when (op) { "+" -> Calculator.add(a, b) "-" -> Calculator.subtract(a, b) "*" -> Calculator.multiply(a, b) "/" -> Calculator.divide(a, b) else -> { println("不支持的操作符: $op") return } } println("$a $op $b = $result") }9.4 编译项目
进入项目根目录,编译所有源文件:
cd calculator kotlinc src/*.kt -include-runtime -d calculator.jar9.5 运行计算器
java -jar calculator.jar 10 + 5输出结果:
10.0 + 5.0 = 15.0再测试一下除法:
java -jar calculator.jar 20 / 4输出结果:
20.0 / 4.0 = 5.0测试除数为零的情况:
java -jar calculator.jar 10 / 0输出结果:
Exception in thread "main" java.lang.IllegalArgumentException: 除数不能为零 at Calculator.divide(Calculator.kt:7) at MainKt.main(Main.kt:20)10. 与 Java 代码混合编译
Kotlin 与 Java 可以无缝互操作,命令行编译同样支持混合编译。
10.1 创建 Java 源文件
创建JavaGreeting.java文件:
public class JavaGreeting { public static String greet(String name) { return "Hello from Java, " + name + "!"; } }10.2 创建 Kotlin 源文件
创建KotlinMain.kt文件:
fun main() { val message = JavaGreeting.greet("Kotlin") println(message) val kotlinMessage = greetFromKotlin("Java") println(kotlinMessage) } fun greetFromKotlin(name: String): String = "Hello from Kotlin, $name!"10.3 混合编译
将 Java 和 Kotlin 源文件一起编译:
kotlinc JavaGreeting.java KotlinMain.kt -include-runtime -d mixed.jar运行程序:
java -jar mixed.jar输出结果:
Hello from Java, Kotlin! Hello from Kotlin, Java!11. 常见问题与排查
在命令行编译过程中,可能会遇到一些常见问题,这里给出排查思路。
11.1 找不到 kotlinc 命令
如果执行kotlinc提示命令不存在,说明 Kotlin 编译器未安装或未加入PATH。请检查安装步骤,并确认kotlinc所在目录已加入环境变量。
11.2 编译时提示找不到符号
当代码引用了其他文件中的类或函数,但编译时未将对应源文件一并传入,就会出现「找不到符号」的错误。解决方法是把相关源文件全部传给kotlinc:
kotlinc MathUtils.kt Main.kt -include-runtime -d app.jar11.3 运行时提示 NoClassDefFoundError
如果编译时未使用-include-runtime,运行 class 文件时需要手动将 Kotlin 标准库加入 classpath:
java -cp classes:kotlin-stdlib.jar HelloKt11.4 第三方依赖运行时找不到
运行包含第三方依赖的程序时,需要将依赖 jar 一并加入 classpath:
java -cp json-demo.jar:libs/gson.jar JsonDemoKt12. 总结
本文系统介绍了 Kotlin 命令行编译的完整流程,包括环境准备、单文件编译、多文件编译、class 文件生成、第三方依赖管理、脚本运行、编译选项、混合编译以及常见问题排查。通过丰富的代码实例,相信读者已经能够熟练使用kotlinc命令完成 Kotlin 项目的编译和运行。
命令行编译虽然不如 IDE 那样可视化,但在自动化构建、CI/CD、服务器部署等场景下具有不可替代的优势。掌握这一技能,可以让你在更多环境中灵活地使用 Kotlin 进行开发。