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

Kotlin SAM/函数式接口访问默认属性抛出AbstractMethodError问题

问题原因

你的假设确实不成立,这个问题是Kotlin面向JVM编译时,SAM转换的实现逻辑和接口默认实现的编译规则不匹配导致的,具体逻辑如下:

  • 默认编译配置下Kotlin接口的编译规则:
    不开启-Xjvm-default相关编译参数时,Kotlin不会把接口里带实现的方法、属性getter直接编译为JVM规范的接口default方法,而是把具体实现存到接口静态内部类DefaultImpls的静态方法中,接口本身对应的方法依然是抽象的。
    对于普通的接口实现类(非SAM转换生成的lambda实例),编译器会自动为所有带默认实现的接口方法生成桥接方法,内部转发调用DefaultImpls里的对应静态逻辑,所以正常写类实现接口时,不管是默认方法还是默认属性,都能正常运行。
  • SAM转换的特殊处理逻辑:
    当你通过lambda表达式构造fun interface的实例时,编译器生成的匿名实现类存在处理遗漏:它只会为接口里的普通成员方法生成调用DefaultImpls的桥接方法,不会为接口中声明的属性对应的getter/setter生成桥接。
    对应到你的代码:
    • SamTest1里的other()是普通成员方法,生成的匿名类中自动生成了对应的桥接方法,调用时会转发到SamTest1.DefaultImpls.other(),所以可以正常输出test。
    • SamTest2里的other是接口属性,对应的getOther()是抽象方法,但SAM生成的匿名类没有为它生成桥接实现,调用这个未实现的方法时,自然会抛出AbstractMethodError。
解决方案

你可以任选以下一种方式修复问题:

  1. 给项目添加编译参数-Xjvm-default=all,强制Kotlin把接口的默认实现直接编译为JVM层面的接口default方法,不需要额外桥接,SAM生成的匿名类类可以直接继承默认实现。注意该参数要求JDK 1.8及以上版本,跨模块依赖时需要所有关联模块都开启该配置。
  2. 避免在fun interface中声明带默认实现的属性,改写为带默认实现的普通成员方法,和SamTest1的写法一致,即可兼容默认编译配置。
  3. 放弃SAM转换,用object表达式显式实现接口,这种场景下编译器会正常生成所有需要的桥接方法,不会抛出错误。示例代码:
val sam2 = object : SamTest2 {
    override fun method1(value: String): Boolean = true
}
println(sam2.other) // 正常输出test

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:18:19