You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中重写Java公共类方法?跨语言调用一致性问题

解决Kotlin与Java调用静态方法行为不一致的问题

首先得明确一个核心点:Java里的静态方法不存在“重写”,只是方法的隐藏(hide)——子类的静态方法只是和父类同名,并不会覆盖父类的静态方法,调用时是根据编译时的类型来决定调用哪个。而Kotlin的companion object默认行为和Java静态方法的JVM实现有差异,这就是导致跨语言调用行为不一致的根源。

为什么会出现你遇到的问题?

  • 最初的Kotlin代码报错:
    • 加override:Kotlin的override关键字只能用于实例方法的重写,静态方法不属于实例成员,所以编译器提示“m1 overrides nothing”。
    • 不加override:你定义的是Kotlin类的实例方法,和父类Java的静态方法m1()的JVM签名冲突,所以报“Accidental override”。
  • 用companion object但不加注解时:
    • Kotlin调用时,会直接解析到companion object里的m1(),所以输出符合预期。
    • Java调用时,BaseTwo.m1()实际上会去调用父类BaseOne的静态方法,因为Kotlin的companion object方法默认是生成在一个名为Companion的内部类中的实例方法,并没有生成真正的JVM静态方法,Java无法直接通过类名调用到它。

解决方案:添加@JvmStatic注解

要让Kotlin和Java调用行为一致,只需要给companion object里的m1()方法加上@JvmStatic注解,强制生成JVM层面的静态方法,这样Java就能正确调用到BaseTwo的静态方法了。

修改后的Kotlin代码:

class BaseTwo : BaseOne() {
    companion object {
        @JvmStatic
        fun m1() {
            println("BaseTwo")
        }
    }
}

此时再用Java主函数调用,输出就会变成:

BaseOne
BaseThree
BaseTwo

和Kotlin主函数调用的结果完全一致。

官方文档相关说明

Kotlin的companion object中的成员默认是作为内部类的实例成员存在的,并非JVM层面的静态成员。如果需要让Java代码像调用普通静态方法一样访问companion object的成员,就必须使用@JvmStatic注解,它会告诉编译器在对应类的JVM字节码中生成一个静态方法,直接映射到companion object的成员方法。

另外,Kotlin不支持静态方法的“重写”逻辑,因为静态成员属于类而非实例,这和Java的设计保持一致,但Kotlin通过companion object来实现类似静态成员的功能,需要通过注解来兼容Java的调用习惯。

内容的提问来源于stack exchange,提问作者dimcha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:09:21