Kotlin与Java互操作:@JvmStatic、@JvmOverloads等注解
请详细说明Kotlin与Java互操作中常用的注解:@JvmStatic、@JvmOverloads、@JvmField、@JvmName等。它们各自解决什么问题?在混合项目中如何使用?Kotlin的空安全类型与Java可空类型如何互转?
回答
编译有声
核心互操作注解
@JvmStatic
问题:Kotlin伴生对象的成员在字节码中是实例方法放在Companion类中,Java调用需KClass.Companion.method()。
解决:将方法暴露为Java静态方法
// Kotlin
class MyClass {
companion object {
@JvmStatic
fun create(): MyClass = MyClass()
}
}
// Java调用:MyClass.create()
@JvmOverloads
问题:Kotlin函数有默认参数,但Java不支持默认参数。
解决:编译器生成多个重载方法
@JvmOverloads
fun greet(name: String = "World", times: Int = 1) { ... }
// 生成:greet() / greet(String) / greet(String, int)
@JvmField
问题:Kotlin属性默认生成private字段+getter/setter。
解决:暴露为public字段(无getter/setter)
@JvmField
val name: String = "hello"
// Java: obj.name (直接字段访问)
@JvmName
问题:Kotlin扩展函数名与Java冲突或需要改名。
解决:指定JVM方法名
空安全互转
// Kotlin
fun nullableFunc(): String? = null
fun nonNullFunc(): String = "hello"
Java中:
nullableFunc()返回@Nullable StringnonNullFunc()返回@NotNull String
JSR-305注解:使用@Nullable/@NonNull可优化Java端的空安全
其他常见问题
- 类型映射:Kotlin
Int↔ Javaint(基本类型),Int?↔Integer(包装类型) - 集合:Kotlin
List↔ JavaList(只读概念丢失),使用Collections.unmodifiableList() - 顶层函数:编译为
FileNameKt类的静态方法,可用@file:JvmName("MyUtils")更改类名