2

在我正在构建的一个小框架中,我想使用 Javassist 将某些抽象类更改为非抽象类。我已经将所有抽象方法转换为实现我需要的动态生成代码的非抽象方法。但是我还没有成功地使这个类成为非抽象类。我尝试过的与此类似:

假设c是我想让非抽象的类。所以我写了:

public void instrument(Class c) {
    ...//some ignored exception management
    CtClass ctClass = ClassPool.getDefault().get(c.getName());
    ctClass.setModifiers(c.getModifiers() & ~Modifier.ABSTRACT);  
    return ctClass.toClass().newInstance();
}

但是,调用:

ctClass.toClass();

正在提出以下问题CannotCompileException

"attempted  duplicate class definition for name: <class_name>."

这是因为该类已经被加载,因为我正在调用它的getName方法。在我看来,这是我必须CtClass从现有课程中获得的唯一机制,但请有人告诉我这是否不正确。硬编码类的名称而不是调用它的getName方法远非一个理想的解决方案,因为我需要将此例程应用于许多类。

任何解决方法可以做到这一点?如果根本不可能,我将动态生成一个扩展抽象类的新类,实现它的构造函数,以及它所有祖先的抽象方法(有点复杂,所以如果我成功制作了原始类非抽象代替)。

4

2 回答 2

3

您是否尝试过创建扩展类而不是更改现有类?所以创建一个类,实现所有方法并使用setSuperClass()它来扩展你的抽象类。

于 2011-11-08T10:15:36.737 回答
1

正如您所描述的,问题在于您已经加载了Class您正在尝试重新定义的内容。尝试重新定义已由类加载器加载的类是非法的。

一种选择可能是做一些类加载器技巧:创建一个新的类加载器,它没有加载现有的类(父类是系统类加载器)并通过它加载 Javassist(使用参数CtClass.toClass()的方法)。ClassLoader

正如它所建议的,可能有更好的方法来实现您的目标,创建子类可能是更好的设计。使用接口而不是抽象类是一种选择吗?如果是这样,动态代理也是一种选择,它们的优点是您不需要任何 3rd 方库来创建它们。

于 2011-11-25T01:34:16.327 回答