13

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

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

我没有足够的权限访问程序来将实例化更改为我的子类,也无法中断原始实例化。

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

我希望这更清楚。

4

4 回答 4

6

重申你正在尝试做的事情..

在 JVM 中,存在一个 ClassA 的实例。您想动态修改 ClassA 的类层次结构,以便存在一个名为 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/

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

于 2012-04-06T16:15:51.833 回答
3

我建议使用cglib

cglib 是一个强大、高性能和高质量的代码生成库,用于扩展 JAVA 类并在运行时实现接口

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

于 2012-04-06T16:17:13.160 回答
2

你看过 Java 代理吗?

这是 Javadoc 的一个片段:

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

于 2012-04-06T16:12:57.180 回答
2

我不知道这是否是一个解决方案,但如果你有

public static Foo foo = new Foo();

并且您想用扩展 Foo 的 Bar 替换它,使 Bar 成为 Foo 的 Wrapper 并使用反射让 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);

}

如前所述,我不知道您的情况是否可行。

于 2012-04-06T17:34:32.160 回答