Java:在运行时扩展类

时间:2012-04-06 16:08:33

标签: java inheritance runtime instantiation

我有能力在编译时扩展一个类,但是我需要能够在运行时使用已经实例化的超类的实例创建这个子类的实例。

这在理论上应该是可能的,因为超类构造函数已经在子类构造函数之前被调用。

我无法充分访问该程序以将实例化更改为我的子类,也无法中断原始实例化。

用例:存在类X的现有实例数组。我的代码在之后加载。我需要覆盖其中一个实例X的一个方法,我的加载子类Y扩展X.父程序只通过该数组访问对象,所以我想用我的Y实例替换该数组元素,但它需要表现得好像它最初被实例化到该数组中。我不能只包含超类实例和转发调用,并且重新实例化超类也很困难。

我希望更清楚。

4 个答案:

答案 0 :(得分:5)

重申你要做的事情......

在JVM中,存在ClassA的实例。您希望动态修改ClassA的类heiarchy,以便存在一个名为ClassB的新类,它派生自ClassA。然后,您希望实例化ClassB的实例,但是它的子类实现是ClassA的现有实例的实现。像记忆替换的东西。

您可能需要查看http://www.jboss.org/javassist。您需要做的是替换ClassLoader,然后确定何时加载ClassA,然后实例化。然后,您需要构造ClassB并返回它。

<强>更新

经过一番研究后,你仍然有可能做你想做的事。 IDE就像Eclipse一样,在调试时支持HotSwap的方法实现。他们使用Instrumentation API。

http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/

您可以替换方法主体,但不能自行添加或删除方法。因此,虽然您无法将类型更改为新类型,但您可以使用新实现完全替换方法实现。

答案 1 :(得分:3)

我建议使用cglib

  

cglib是一款功能强大,性能卓越,质量上乘的代码   库,它用于扩展JAVA类并实现接口   在运行时

您可以在此处找到一些示例: https://github.com/cglib/cglib/wiki

答案 2 :(得分:2)

我不知道它是否是溶剂,但如果你有

public static Foo foo = new Foo();

并且您希望将其替换为扩展Foo的Bar 使Bar成为Foo的包装器并使用反射让foo指向你的Bar实例。

public class Foo extends Bar {
  private bar; 
  public Foo(Bar oldInstance) {
     this.bar = oldInstance;
  }
}

// exception handling ommitted
public static void onStartup() {
   Class fooRefClass = FooRef.class;
   Field fooRef = fooRefClass.getDeclaredField("foo");

   Foo foo = (Foo)fooRef.get(null);
   Bar bar = new Bar(foo);
   fooRef.set(null, bar);

}

据我所知,我不知道你的情况是否可行。

答案 3 :(得分:1)

你看过Java Proxies吗?

以下是Javadoc的片段:

“动态代理类(下面简称为代理类)是一个实现创建类时在运行时指定的接口列表的类”