![](/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.