【Kotlin】互操作之Java调用Kotlin避坑指南
·
前言
Java 不能直接理解 Kotlin 语法(顶层函数、伴生对象、data class、suspend、private 等),Kotlin 会编译成特殊的 Java 结构,Java 必须按编译后的规则调用。
下面是精心整理的常用避坑速查清单:
一、顶层函数/顶层常量(*.kt 文件内直接定义)
Kotlin 代码(文件名:FileUtil.kt)
fun printLog(msg: String) {}
const val VERSION = "2.1.0"
val desc = "工具类"
Java 调用规则
- 函数/普通属性:文件名+
Kt作为类名调用 const val编译期常量可直接静态访问
FileUtilKt.printLog("test");
String v = FileUtilKt.VERSION;
String d = FileUtilKt.getDesc();
约束
不能直接 FileUtil.printLog(),必须带后缀 Kt;普通 val 在 Java 是 getXXX()。
二、companion object 伴生对象
原始写法(无注解)
class User {
companion object {
fun create() {}
const val MAX = 100
}
}
Java 调用:
User.Companion.create();
int max = User.MAX;
规范优化:添加 @JvmStatic,消除 Companion
companion object {
@JvmStatic fun create() {}
const val MAX = 100
}
Java 简洁调用:
User.create();
约束
不加 @JvmStatic 必须写 .Companion;const val 不受影响。
三、带默认值的函数参数
无注解(Java 强制传全量参数)
fun show(name: String, age: Int = 18) {}
Java 只能完整传参:
show("Tom", 18);
// show("Tom"); 编译报错
规范优化:@JvmOverloads 生成多重载方法
@JvmOverloads
fun show(name: String, age: Int = 18) {}
Java 两种调用都支持:
show("Tom");
show("Tom", 20);
约束
Java 原生不识别 Kotlin 默认参数,不加注解无法省略参数。
四、单例 object 类
Kotlin
object HttpManager {
fun request() {}
}
Java 调用
HttpManager.INSTANCE.request();
约束
没有静态方法,必须通过内置 INSTANCE 对象访问;
如需静态调用,函数上加 @JvmStatic:
object HttpManager {
@JvmStatic fun request() {}
}
// Java
HttpManager.request();
五、Kotlin 属性 val / var
Kotlin
class Book {
val id: Long = 1L // 只读
var title: String = "" // 可读可写
}
Java 调用(自动生成 getter / setter)
Book book = new Book();
long id = book.getId();
String t = book.getTitle();
book.setTitle("Kotlin实战");
约束
Java 不能直接 .id / .title,必须使用 getter/setter。
六、internal 修饰符(模块内可见)
Kotlin
internal fun innerFunc() {}
internal val code = 200
约束
Java 完全无法访问,编译直接报错;跨模块/Java 代码不要用 internal。
七、空安全类型(关键坑点)
Kotlin 不可空(String,禁止null)
fun setName(name: String) {}
Java 可强行传入 null,运行抛出空指针:
setName(null); // 运行崩溃
Kotlin 可空(String?)
fun setNick(nick: String?) {}
Java 传 null 安全:
setNick(null);
规范
对外提供给 Java 调用的接口,不确定入参是否为空时,统一声明可空 ?。
八、suspend 挂起函数(Java 无法直接调用)
Kotlin
suspend fun fetchData(): String { return "" }
约束
Java 不存在协程上下文,直接调用编译报错。
规范方案
封装普通函数,使用协程调度器包装,提供 Java 可用回调接口:
fun fetchDataJava(callback: (String) -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
val res = fetchData()
callback(res)
}
}
Java 调用:
fetchDataJava(result -> {
System.out.println(result);
return Unit.INSTANCE;
});
九、高阶函数 / Lambda 参数
Kotlin
fun listenEvent(block: (Int) -> Unit) {}
Java 调用规范
使用 Function1,返回值必须携带 Unit.INSTANCE
listenEvent(num -> {
System.out.println(num);
return Unit.INSTANCE;
});
十、data class 数据类
Kotlin
data class Student(val name: String, val age: Int)
Java 使用
- 构造正常 new
- 获取属性推荐 getter,不推荐 component 组件函数
Student s = new Student("Jack", 16);
String name = s.getName(); // 推荐
int age = s.getAge();
// s.component1() 不推荐,可读性差
十一、常用注解速记(Java 适配专用)
| 注解 | 作用场景 | 效果 |
|---|---|---|
| @JvmStatic | companion object / object | 生成静态方法,Java 无需写 Companion/INSTANCE |
| @JvmOverloads | 带默认参数函数 | Java 生成多个重载,支持省略参数 |
| @JvmField | val/var 属性 | Java 可直接访问字段,不用 getter |
| @JvmName | 顶层文件 | 修改 Java 生成的类名,去掉 Kt 后缀 |
十二、核心约束总览(一句话总结)
- 顶层函数带
Kt后缀; - 伴生/单例不加
@JvmStatic必须写 Companion / INSTANCE; - Java 不支持默认参数、suspend、internal;
- Kotlin 属性在 Java 只能通过 getter/setter;
- Java 可传 null 破坏 Kotlin 非空校验,线上易空指针;
- Lambda 需要返回
Unit.INSTANCE。
更多推荐


所有评论(0)