在调用实现接口的泛型方法时出错:java.lang.AbstractMethodError



我正在尝试使用javassist以编程方式创建和编译实现接口的类(在运行时)。

当我调用这个动态类的实例时,我得到以下错误:

java.lang.AbstractMethodError: FooImpl.test()Ljava/lang/Object;

这是我的界面

public class FooBarInterface<T> {
    public T getEntity();
}

这是一个示例实体

public class FooEntity {
    @Override
    public String toString() {
        return "Hello, Foo!";
    }
}
下面是我如何通过编程实现接口
public void test() {
    ClassPool classPool = ClassPool.getDefault();
    CtClass testInterface = classPool.get(FooBarInterface.class.getName());
    CtClass fooImpl = classPool.makeClass("FooImpl");
    fooImpl.addInterface(testInterface);
    CtMethod testMethod = CtNewMethod.make(
        "public com.test.FooEntity getEntity(){" +
            "return new com.test.FooEntity();" +
        "}",
        canImpl
    );
    fooImpl.addMethod(testMethod);
    fooImpl.writeFile();
    TestInterface<FooEntity> test = 
        (TestInterface<FooEntity>) fooImpl.toClass().newInstance();
    System.out.println(test.getEntity());
}

如果我将实现的方法的返回类型更改为Object,那么我不会得到错误,像这样:

CtMethod testMethod = CtNewMethod.make(
    "public Object getEntity(){" +
        "return new com.test.FooEntity();" +
    "}",
    canImpl
);

则成功获取hello, Foo!。我可以将返回类型更改为对象,但我想了解更多为什么使用类型Foo返回产生AbstractMethodError

在JVM内部,具有不同返回类型的方法是不同的。类型擦除后,FooBarEntity.getEntity()有返回类型Object。通过接口调用将专门寻找返回类型为Object的方法,因此为什么你的实现必须返回Object

通常,您的Java编译器将创建桥接方法,将具体方法的结果转发为擦除类型,但显然Javassist不会为您这样做(我没有使用Javassist,所以我不确定)。

有关如何使用桥方法实现类型擦除的更多信息,请参阅关于桥方法的官方Java教程主题。

我也有同样的错误。我有一个基类,在其中声明了一个新的抽象方法。我在其他使用它的类上实现了那个方法。现在在调试中,我一碰到方法的实现就得到了抽象方法错误。

解决方案- - -:我认为基类也会被其他构件所使用,并且我没有覆盖那些构件中新创建的抽象方法。因为我从来没有构建它们,因为我没有改变它们,JVM从来没有抛出编译时错误,但在运行时异常发生。在其他工件中实现方法时,我能够摆脱异常。基本上在我的情况下,所有子类都没有实现基类的抽象方法。

当您有一个参数化的参数或返回类型时,Java编译器将它当作Object来编译,并合成一个具有调用另一个参数化签名的桥接方法。或者反过来也有可能。您只合成了其中一个,而不是两个。

相关内容

  • 没有找到相关文章

最新更新