Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
错误:调用实现接口的泛型方法时发生java.lang.AbstractMethodError_Java_Generics_Javassist_Java Bridge Method - Fatal编程技术网

错误:调用实现接口的泛型方法时发生java.lang.AbstractMethodError

错误:调用实现接口的泛型方法时发生java.lang.AbstractMethodError,java,generics,javassist,java-bridge-method,Java,Generics,Javassist,Java Bridge Method,我试图使用javassist以编程方式创建和编译一个实现接口的类(在运行时) 每当调用该动态类的实例时,都会出现以下错误: java.lang.AbstractMethodError: FooImpl.test()Ljava/lang/Object; 这是我的界面 public class FooBarInterface<T> { public T getEntity(); } public void test() { ClassPool classPool =

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

每当调用该动态类的实例时,都会出现以下错误:

java.lang.AbstractMethodError: FooImpl.test()Ljava/lang/Object;
这是我的界面

public class FooBarInterface<T> {
    public T getEntity();
}
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());

}
下面是我如何编程实现接口的

public class FooBarInterface<T> {
    public T getEntity();
}
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());

}

然后我成功地得到了
你好,Foo。我同意将返回类型更改为Object,但我想进一步了解为什么使用Foo类型返回会产生
AbstractMethodError

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

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


有关如何使用桥接方法实现类型擦除的详细信息,请参阅。

当您有参数化参数或返回类型时,Java编译器将其编译为对象,并使用调用另一个参数化签名合成桥接方法。或者可能相反。您只合成了其中一个,而不是两个。

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

解决方案-: 我认为基类也被其他工件占用了,并且我没有在这些工件中重写新创建的抽象方法。由于我从未在不更改它们时构建它们,所以JVM从未抛出编译时错误,但在运行时发生异常。
在其他工件中实现方法时,我能够消除异常。在我的情况下,基本上所有子类都没有基类的抽象方法的实现。

ClassPool ClassPool=ClassPool.getDefault()这些类不在标准java库中。这是第三方图书馆?是的,你说得对!我正在使用的第三方库是javassist(尽管在我的问题中提到过),谢谢您提供的信息!在学习了更多关于类型擦除的知识后,我终于找到了答案。谢谢你的回答!。我将尝试检查javassist文档是否也支持合成具有特定类型的实现。在我的例子中,我不知道在类型擦除期间,当JVM编译时,它会自动将桥接方法添加到子类型(泛型类/接口)以保留多态性。因为我在运行时使用javassist编译类,所以我没有从自动获取桥接方法中获益——或者至少,我不知道如何告诉javassist提供桥接方法。