简体   繁体   English

错误:调用实现接口的通用方法时,java.lang.AbstractMethodError

[英]Error: java.lang.AbstractMethodError when invoking a generic method implementing an interface

I am trying to use javassist to programatically create and compile a class (at runtime) that implements an interface. 我正在尝试使用javassist以编程方式创建和编译实现接口的类(在运行时)。

I get the following Error whenever I invoke an instance of that dynamic class: 每当我调用该动态类的实例时,都会收到以下错误消息:

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

Here's my interface 这是我的界面

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

Here's a sample Entity 这是一个示例实体

public class FooEntity {

    @Override
    public String toString() {
        return "Hello, Foo!";
    }
}

Here's how I programatically implement the interface 这是我以编程方式实现接口的方式

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());

}

If I changed the return type of the implemented method to Object, then I don't get the Error, like this: 如果我将实现的方法的返回类型更改为Object,则不会收到错误,如下所示:

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

Then I successfully get the hello, Foo! 然后我成功地打了hello, Foo! . I am OK with changing the return type to Object, but I'd like to understand more why returning with type Foo produces AbstractMethodError . 我可以将返回类型更改为Object,但是我想进一步了解为什么使用Foo类型返回会产生AbstractMethodError

Inside the JVM, methods with different return types are distinct. 在JVM内部,具有不同返回类型的方法是不同的。 After type erasure, FooBarEntity.getEntity() has return type Object . 类型擦除后, FooBarEntity.getEntity()返回类型为Object Calls via the interface will look specifically for a method with return type Object , hence why your implementation must return Object . 通过接口进行的调用将专门查找具有返回类型Object的方法,因此为什么您的实现必须返回Object

Normally, your Java compiler will create bridge methods that forward the result of the concrete method as the erased type, but apparently Javassist doesn't do this for you (I haven't used Javassist so I'm not sure). 通常,您的Java编译器将创建桥接方法,以将具体方法的结果作为已擦除类型转发,但是显然Javassist不会为您执行此操作(我没有使用Javassist,因此不确定)。

For more on how bridge methods are used to implement type erasure, see the official Java Tutorials topic on bridge methods . 有关如何使用桥方法实现类型擦除的更多信息,请参见关于桥方法官方Java教程主题

When you have a parameterized parameter or return type, the Java compiler compiles it as though it was Object and synthesizes a bridge method with the parameterized signature that calls the other one. 当您有参数化的参数或返回类型时,Java编译器将其编译为好像是Object一样,并使用带有参数化签名的桥方法合成桥方法,该签名方法将调用另一个方法。 Or possibly the other way around. 或可能相反。 You've only synthesized one of them, not both. 您只合成了其中一个,而不是两者都合成。

I was having same error. 我有同样的错误。 I had a base class in which I declared a new abstract method. 我有一个基类,在其中声明了一个新的抽象方法。 I implemented that method on the other classes that were consuming it. 我在使用它的其他类上实现了该方法。 Now on debugging I was getting Abstract method error as soon as I was hitting implementation of the method. 现在在调试时,一旦达到方法的实现,就会遇到Abstract方法错误。

Solution-: I figured that base class been consumed by other artifacts too and I didn't overrode newly created abstract method in those artifacts. 解决方案:我发现基类也被其他工件占用,并且没有覆盖这些工件中新创建的抽象方法。 Since I never build them as I was not changing them, JVM never throws compile time error but on run time exception occurs. 由于我从未更改过它们,所以我从未构建它们,因此JVM永远不会引发编译时错误,但会在运行时发生异常。 On implementing method in other artifacts I was able to get rid of the exception.Basically in my case all child classes didn't have implementation of base class's abstract method. 在其他工件中实现方法时,我能够摆脱异常。基本上在我的情况下,所有子类都没有实现基类的抽象方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 字节好友:java.lang.AbstractMethodError:调用方法时出错 - Byte Buddy: java.lang.AbstractMethodError: error when invoking method 在实现的方法上获取 java.lang.AbstractMethodError - Getting java.lang.AbstractMethodError on implemented method java.lang.AbstractMethodError: 抽象方法未实现 - java.lang.AbstractMethodError: abstract method not implemented java.lang.AbstractMethodError - java.lang.AbstractMethodError 错误StatusLogger捕获java.lang.AbstractMethodError - ERROR StatusLogger Caught java.lang.AbstractMethodError javassist和抽象通用类的java.lang.AbstractMethodError - java.lang.AbstractMethodError with javassist and abstract generic classes java.lang.AbstractMethodError:在sqlite上调用createArrayOf方法时出现org.sqlite.Conn.createArrayOf错误 - java.lang.AbstractMethodError: org.sqlite.Conn.createArrayOf error while calling createArrayOf method on sqlite 如何解决对init方法的调用失败:java.lang.AbstractMethodError - How to solve invocation of init method failed: java.lang.AbstractMethodError 在ReportClientDocument.open()调用中获取错误java.lang.AbstractMethodError - Getting error java.lang.AbstractMethodError on ReportClientDocument.open() call JavaToWS 错误:java.lang.AbstractMethodError 从类生成 Web 服务 - JavaToWS Error: java.lang.AbstractMethodError generating a webservice from classes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM