首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Kotlin /Functional抛出AbstractMethodError

Kotlin /Functional抛出AbstractMethodError
EN

Stack Overflow用户
提问于 2022-06-24 00:32:23
回答 1查看 89关注 0票数 2

为什么SamTest2接口在访问other属性时抛出一个AbstractMethodError?接口中提供了默认实现,因此我假设在main方法中创建的匿名实例将正常工作。这是一个错误的假设吗?

代码语言:javascript
复制
fun interface SamTest1 {

  fun method1(value: String): Boolean

  fun other(): String = "test"
}

fun interface SamTest2 {

  fun method1(value: String): Boolean

  val other: String
    get() = "test"
}

fun main() {
  val sam1 = SamTest1 { true }
  println(sam1.other()) // test

  val sam2 = SamTest2 { true }
  println(sam2.other) // AbstractMethodError
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-24 01:55:31

我正在查看为您的代码生成的JVM字节码。SamTest1SamTest2看起来几乎相同(除了内部事物的一些名称之外),这是有意义的,因为在JVM方面,val与相同类型的0参数fun没有什么不同。

代码语言:javascript
复制
public interface SamTest1 {
    public boolean method1(@NotNull String var1);

    public String other();

    public static final class DefaultImpls {
        public static String other(SamTest1 this_) {
            return "test";
        }
    }
}

public interface SamTest2 {
    public boolean method1(@NotNull String var1);

    public String getOther();

    public static final class DefaultImpls {
        public static String getOther(SamTest1 this_) {
            return "test";
        }
    }
}

当我们看到你的main时,最令人兴奋的部分来了。清理一些文物,看起来就像

代码语言:javascript
复制
static final class sam1$1 implements SamTest1 {
    public static final sam1$1 INSTANCE = new sam1$1();

    public final boolean method1(String it) {
        return true;
    }

    public String other() {
        return SamTest1.DefaultImpls.other(this);
    }

}

public static final void main() {
    SamTest1 sam12 = sam1$1.INSTANCE;
    System.out.println(sam12.other());
    SamTest2 sam2 = samKt::main$lambda$0;
    System.out.println(sam2.getOther());
}

private static final boolean main$lambda$0(String it) {
    return true;
}

因此,据我所知,Kotlin认识到SamTest1有两个方法,因此(就Java而言)不是SAM接口,因此它创建了一个新类来表示匿名实例。方法的默认值将在匿名类中传递(就像在Kotlin中应该发生的那样),一切都很好。

但是Kotlin似乎认为SamTest2与Java的SAM接口机制是兼容的,并且简单地传递给它一个方法samKt::main$lambda$0,希望JVM端的SAM机制能够综合地构造对象。如果实际上有一个抽象方法,但是JVM端有两个:method1getOther,所以后者在调用时会得到AbstractMethodError,这会很好。

我很想在这件事上被证明是错的,但我认为这是一个Kotlin的错误。它应该为每个人生成合成类。我在bug跟踪器上找不到类似的问题,但是我认为编译器的行为在这里是不正确的。

注意:我使用CFR将JVM字节码反编译回Java。我删除了许多空检查、元数据注释和类型转换,以使文章简洁。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72737899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档