Java 调用 Kotlin 代码
1. 基本互操作规则
Kotlin 代码编译后会生成标准的 JVM 字节码,因此 Java 可以无缝调用 Kotlin 代码,但需要注意以下特性:
- 文件名与类名:Kotlin 顶层函数会生成包含
Kt后缀的类(如Utils.kt→UtilsKt) - 属性访问:Kotlin 属性会编译为
getter/setter方法(val只有 getter) - 伴生对象:通过
Companion字段访问(除非使用@JvmStatic注解)
2. 关键注解的使用
@JvmName
修改生成的 Java 类/方法名:
@file:JvmName("StringUtils") // 改变生成的类名
fun capitalize(str: String): String = str.capitalize()
Java 调用:
StringUtils.capitalize("hello");
@JvmStatic
使伴生对象成员显示为静态方法:
class Calculator {
companion object {
@JvmStatic
fun add(a: Int, b: Int) = a + b
}
}
Java 调用:
Calculator.add(2, 3); // 无需通过 Companion
@JvmOverloads
为带默认参数的函数生成重载方法:
@JvmOverloads
fun greet(name: String, prefix: String = "Mr.") {
println("Hello, $prefix $name")
}
Java 中会生成两个方法:
greet("Alice"); // 使用默认参数
greet("Bob", "Dr."); // 显式传参
3. 特殊类型处理
函数类型
Kotlin 的 lambda 会编译为 FunctionN 接口:
fun runOperation(op: (Int, Int) -> Int) {
println(op(5, 3))
}
Java 调用:
runOperation((a, b) -> a + b); // 使用 SAM 转换
平台类型
当 Kotlin 代码返回可能为 null 的类型时,Java 会看到平台类型(如 String!),需要自行处理 null 安全:
String name = KotlinUtils.getName(); // 可能抛出 NPE
4. 异常处理差异
Kotlin 没有受检异常,Java 调用时异常会被自动转换为非受检异常:
fun readFile() throws IOException { ... }
Java 调用时不需要 try-catch(除非强制处理)。
5. 集合互操作
Kotlin 集合在 Java 中表现为:
List→java.util.List(但可能是不可变的)MutableList→java.util.List
建议使用转换方法:
List<String> javaList = KotlinUtils.getKotlinList();
List<String> mutableList = new ArrayList<>(javaList); // 转为可修改
最佳实践
- 对需要 Java 调用的 API 添加
@JvmStatic和@JvmOverloads - 避免在公共 API 中使用高阶函数(Java 调用不友好)
- 为可能返回 null 的方法添加
@Nullable注解 - 使用
kotlin.collections.CollectionsKt中的扩展方法增强 Java 集合功能
示例项目:包含完整的 Java 调用 Kotlin 的示例代码可在书籍配套 GitHub 仓库查看。
