如何使用Javassist创建一个非抽象的抽象类?

时间:2011-11-08 02:21:37

标签: java classloader javassist

在我正在构建的小框架中,我想使用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方法远非理想的解决方案,因为我需要将这个例程应用于许多类。

要做到这一点的任何解决方法吗?如果根本不可能,我会动态生成一个扩展抽象类的新类,实现它的构造函数,以及它所有祖先的抽象方法(有点复杂,所以如果我成功的话,我会非常高兴原始类非抽象而非)。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

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

正如它所建议的,可能有更好的方法来实现您的目标,创建子类可能是更好的设计。使用接口而不是抽象类是一个选项吗?如果是这样,dynamic proxies也是一个选项,他们的优势在于您不需要任何第三方库来创建它们。