![](/img/trans.png)
[英]Byte Buddy: java.lang.AbstractMethodError: error when invoking method
[英]Error: java.lang.AbstractMethodError when invoking a generic method implementing an interface
我正在尝试使用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!
。 我可以将返回类型更改为Object,但是我想进一步了解为什么使用Foo类型返回会产生AbstractMethodError
。
在JVM内部,具有不同返回类型的方法是不同的。 类型擦除后, FooBarEntity.getEntity()
返回类型为Object
。 通过接口进行的调用将专门查找具有返回类型Object
的方法,因此为什么您的实现必须返回Object
。
通常,您的Java编译器将创建桥接方法,以将具体方法的结果作为已擦除类型转发,但是显然Javassist不会为您执行此操作(我没有使用Javassist,因此不确定)。
有关如何使用桥方法实现类型擦除的更多信息,请参见关于桥方法的官方Java教程主题 。
当您有参数化的参数或返回类型时,Java编译器将其编译为好像是Object一样,并使用带有参数化签名的桥方法合成桥方法,该签名方法将调用另一个方法。 或可能相反。 您只合成了其中一个,而不是两者都合成。
我有同样的错误。 我有一个基类,在其中声明了一个新的抽象方法。 我在使用它的其他类上实现了该方法。 现在在调试时,一旦达到方法的实现,就会遇到Abstract方法错误。
解决方案:我发现基类也被其他工件占用,并且没有覆盖这些工件中新创建的抽象方法。 由于我从未更改过它们,所以我从未构建它们,因此JVM永远不会引发编译时错误,但会在运行时发生异常。 在其他工件中实现方法时,我能够摆脱异常。基本上在我的情况下,所有子类都没有实现基类的抽象方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.