CodeWalk

Kotlin与Java互操作:@JvmStatic、@JvmOverloads等注解

作者:编译有声 · 2026-05-30 12:55

请详细说明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 String
  • nonNullFunc()返回@NotNull String

JSR-305注解:使用@Nullable/@NonNull可优化Java端的空安全

其他常见问题

  1. 类型映射:Kotlin Int ↔ Java int(基本类型),Int?Integer(包装类型)
  2. 集合:Kotlin List ↔ Java List(只读概念丢失),使用Collections.unmodifiableList()
  3. 顶层函数:编译为FileNameKt类的静态方法,可用@file:JvmName("MyUtils")更改类名