在Java中,是否有可能动态地将一个父类注入到类层次结构中?

6

给定一个类层次结构:

A -> B -> C -> instanceOfC

是否可以在运行时临时插入一个类,如下所示:

A -> B -> B' -> C -> instanceOfC?

(译者注:即在B和C之间插入一个新的类B')
4个回答

6

AspectJ

如果您使用AspectJ,那么这是可能的。AspectJ有一个declare parents语句,可以让您做到这一点,并且通过Load Time Weaving,您也应该能够在运行时实现它。但是,您将无法对已加载的类执行此操作(至少不容易,也许如果您先卸载类,它会起作用)。

参考资料:

继承与聚合

但我认为您正在尝试解决错误的问题。我建议尝试使用聚合替换继承,让C拥有类型为D的成员,将功能委托给它,并传入不同的D实现。这被称为策略模式,它是一种更清晰的方法(而且也可以进行测试)。


+1 对于“在某些情况下是可能的”——即使这有点作弊,也算符合问题中的“Java”部分。 - user166390

3

允许对正在运行的JVM进行最深入更改的API可能是JVM工具接口。它旨在开发调试器,可以在运行时动态更改方法以便于进行修复和继续调试。

替换类定义的相关调用将是RedefineClass。但是,文档指出它不能用于更改类的层次结构:

重新定义不能添加、删除或重命名字段或方法,更改方法的签名、更改修饰符或更改继承关系。

因此,我认为您无法在未修改的JVM中合理地修改已加载的类的类型层次结构。要么在加载期间更改类层次结构(使用自定义ClassLoader和字节码注入,可能使用AOP),要么找到另一种方法。


1

不可以。

你可以做:

A -> | interface for B and B` | -> C

或者

     | B  | -> C
A -> 
     | B` | -> C`

失去一些良好的习惯,你可以这样做:B + 内部类 = B'

例如:

public class B<extraFunctionalityClassOrInterface> extends A {
    private extraFunctionalityClassOrInterface eF = null;
    // and B contents
}

如果b.eF == null的实例,则可以得出结论b!= B',但b == B


0

我不是百分之百确定,但我认为只有在同时动态加载B'和C时才可能实现这一点。


如果您能指向一些已经实现此功能的示例代码,那将非常棒。 - blueberryfields
1
在我开始使用自定义类加载器之前,这似乎是一个设计缺陷。在什么样的情况下你需要这么做? - jerluc
这似乎是一个潜在的解决方案,可以解决此问题:http://programmers.stackexchange.com/questions/41925/how-do-i-inject-test-objects-when-the-real-objects-are-created-dynamically - 这也将有助于解决两个非Java专家之间的一些争议。 - blueberryfields
嗯,我仍然不明白为什么在没有其他设计替代方案的情况下您需要这样做,但是正如您发布的链接中提到的那样,我知道的唯一方法涉及大量接口的构建。 - jerluc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接