我想创建一个类的对象,并覆盖它的一些方法。例如:
Foo bar = new Foo(){
public void fighters(){
//some stuff
}
};
问题是:类的名称存储在一个String中。我显而易见的做法是使用Constructor.newInstance(Objecto)方法创建一个新实例,如下所示:
Class c = cl.loadClass("com.pom.Foo");
Foo f = (Foo) (c.getDeclaredConstructor(String.class).newInstance("Hello!"));
尽管这段代码成功地创建了该类的一个新实例,但我现在不知道如何重写它的方法。
有什么建议吗?
我认为你有几个选择,没有一个是好的,而且都是关于如何解决所面临的问题的建筑问题。
委托包装
创建一个DelegangFoo类,如下所示:
class DelegatingFoo {
Callable callMe;
public DelegatingFoo(Callable callMe) {
this.callMe = callMe;
}
public void fighters(){
calLMe.call();
}
};
相反,将其实例化,将一个Callable对象传递到构造函数中,如上面所述。这会使您想要运行的代码与注入它的位脱节。
使用JVM语言
编译到可以通过javax.script运行的东西,如BeanShell、Groovy等。根据您最终要做的事情,这可能是一个可行的选项。
自定义类加载器
如果您可以选择使用一个替代类加载器(它呈现自己的问题),这将充满它自己的问题,并创建一些非常复杂的东西。如果你决定认真考虑这一点,那么看看像OSGi类加载框架这样的东西可能会给你一些线索(在某种程度上,它甚至可能是合适的)。
字节码操作
有几个库可以帮助实时执行字节码挖掘/拦截/生成/更改:
- BECL-http://commons.apache.org/bcel/
- CGLib-http://cglib.sourceforge.net/
警告
需要注意的是,以上都是技巧,随着你往下走,堕落程度会越来越高。我会尽快得到我的建筑同行的审查,因为我会把钱花在那里做一个清洁工&对你正在做的事情采取更清晰的方法。
记住,你写的代码应该更容易阅读,否则你会给自己(或未来的项目所有者)带来维护难题。