当前位置:  开发笔记 > 编程语言 > 正文

Byte Buddy:为抽象类创建实现

如何解决《ByteBuddy:为抽象类创建实现》经验,为你挑选了1个好方法。

我想在运行时为使用Byte Buddy的抽象类创建一个实现,我面临的问题java.lang.AbstractMethodError是,从创建的实例调用方法时会抛出a.我有一个abstract像这样的现有类(我实际上无法修改,实际上包含更多逻辑):

public abstract class Algorithm {
    abstract int execute();
}

使用以下最小样本,我希望我的Algorithm实例返回一个常量值:

Class type = new ByteBuddy()
                        .subclass(Algorithm.class)
                        .method(ElementMatchers.named("execute"))
                        .intercept(FixedValue.value(42))
                        .make()
                        .load(classLoader, ClassLoadingStrategy.Default.WRAPPER)
                        .getLoaded();
Algorithm instance = (Algorithm) type.newInstance();
System.out.println(myInstance.execute());

然而,这会导致以下异常:

Exception in thread "main" java.lang.AbstractMethodError: package.Algorithm.execute()I

(当我实验性地Algorithm改为a时interface,一切正常,但这并不能解决我的具体问题).



1> Rafael Winte..:

它可能会让您感到惊讶,但如果您使用相同的类加载器设置使用javac生成相同的代码,则会发生完全相同的事情.您在JLS中如何指定package-privacy暗示了您所观察到的内容.你的非接口

public abstract class Algorithm {
  abstract int execute(); 
}

定义了一个包私有方法.由于您没有为生成的类定义自定义名称,因此Byte Buddy会生成一个具有随机名称的子类,该子类位于同一个包中.Byte Buddy进一步发现该executable方法可以从生成的子类中重写,并完全按照您的预期实现它.

但是,您正在使用该ClassLoadingStrategy.Default.WRAPPER策略来加载类,该类创建一个加载的新子类加载器Algorithm.在Java中,在运行时,如果包的名称相同并且两个包都由相同的包加载ClassLoader,则两个包仅相等.对于您的情况,后一种情况并非如此,以至于JVM不再将多态性应用于execute该类.通过电话

((Algorithm) type.newInstance()).execute();

因此,您不是调用生成的方法,而是调用原始的抽象方法.因此 - 按照JLS - 一个AbstractMethodError被抛出.

要解决此问题,您需要使用默认INJECTION策略在同一个包中加载生成的类,或者您必须定义executepublic(这在定义接口时是隐式的)或protected方法,以便您希望执行多态的规则应用.作为第三个选项,您可以通过调用正确的运行时方法

type.getDeclaredMethod("execute").invoke(type.newInstance());

推荐阅读
家具销售_903
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有