Java:在运行时扩展类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10046056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: Extending Class At Runtime
提问by JAKJ
I have the capability to extend a class at compile time, but I need to be able to create an instance of this subclass at runtime using an instance of the superclass that was already instantiated.
我有能力在编译时扩展一个类,但我需要能够在运行时使用已经实例化的超类的实例创建这个子类的实例。
This should be possible in theory because superclass constructors are already called before the subclass constructor.
这在理论上应该是可能的,因为在子类构造函数之前已经调用了超类构造函数。
I do not have access to the program sufficiently to change the instantiation to my subclass nor to interrupt the original instantiation.
我无法充分访问该程序,无法将实例化更改为我的子类,也无法中断原始实例化。
Use Case: There is an existing array of instances of class X. My code is loaded in after. I need to override one of the methods of one of the instances X with my loaded subclass Y extends X. The parent program accesses the objects only through that array, so I want to replace that array element with my Y instance, but it needs to behave as if it were instantiated originally into that array. I cannot just enclose the superclass instance and forward calls, and there are difficult complications with reinstantiating the superclass.
用例:存在类 X 的实例数组。我的代码在之后加载。我需要用我加载的子类 Y extends X 覆盖实例 X 之一的方法。父程序仅通过该数组访问对象,所以我想用我的 Y 实例替换该数组元素,但它需要表现得好像它最初被实例化到该数组中一样。我不能只包含超类实例和转发调用,并且重新实例化超类存在困难的并发症。
I hope that is more clear.
我希望这更清楚。
采纳答案by Andrew T Finnell
To reiterate what you are trying to do..
重申您正在尝试做的事情..
Within the JVM, there exists an instance of ClassA. You would like to dynamically modify the class heiarchy of ClassA, such that a new class exists called ClassB which derives from ClassA. Then you would like to instantiate an instance of ClassB but have it's subclass implementation be that of the existing instance of ClassA. Something like a memory replacement.
在 JVM 中,存在 ClassA 的一个实例。您想动态修改 ClassA 的类层次结构,以便存在一个名为 ClassB 的新类,它是从 ClassA 派生的。然后你想实例化一个 ClassB 的实例,但它的子类实现是 ClassA 的现有实例的子类实现。类似于内存更换。
You might want to look into http://www.jboss.org/javassist. What you would need to do is replace the ClassLoader, then determine when ClassA is being loaded, then instantiated. You'd then need to construct ClassB and return that instead.
您可能想查看http://www.jboss.org/javassist。您需要做的是替换 ClassLoader,然后确定何时加载 ClassA,然后实例化。然后您需要构造 ClassB 并返回它。
Update
更新
After a little more research there is still the possibility you can do what you want. IDE's like Eclipse support HotSwap'ing method implementations while debugging. They use the Instrumentation API.
经过更多的研究,您仍然有可能做自己想做的事。IDE 之类的 Eclipse 支持在调试时实现 HotSwap 方法。他们使用 Instrumentation API。
http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/
http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/
You can replace method bodies but not add or remove methods themselves. So while you won't be able to change the type to your new type, you can completely replace the method implementation with your new implementation.
您可以替换方法主体,但不能添加或删除方法本身。因此,虽然您无法将类型更改为新类型,但您可以使用新实现完全替换方法实现。
回答by Lefteris Laskaridis
I would suggest using cglib:
我建议使用cglib:
cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime
cglib 是一个强大的、高性能的、高质量的代码生成库,用于在运行时扩展 JAVA 类和实现接口
You may find some examples here: https://github.com/cglib/cglib/wiki
你可以在这里找到一些例子:https: //github.com/cglib/cglib/wiki
回答by andih
I don't know if it's a sollution but if you have
我不知道这是否是一种解决方案,但如果你有
public static Foo foo = new Foo();
and you want to replace it with Bar which extends Foo make Bar an Wrapper for of Foo and use reflection to let foo point to your Bar instance.
并且你想用 Bar 替换它,它扩展了 Foo 使 Bar 成为 Foo 的包装器并使用反射让 foo 指向你的 Bar 实例。
public class Foo extends Bar {
private bar;
public Foo(Bar oldInstance) {
this.bar = oldInstance;
}
}
and
和
// 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);
}
}
As told I don't know if this is possible in your case.
如上所述,我不知道这在您的情况下是否可行。
回答by Alex Paransky
Have you looked at Java Proxies?
你看过 Java 代理吗?
Here is a snippet from Javadoc:
这是 Javadoc 的一个片段:
"A dynamic proxy class (simply referred to as a proxy class below) is a class that implements a list of interfaces specified at runtime when the class is created"
“动态代理类(以下简称代理类)是一个类,它实现了类创建时在运行时指定的接口列表”