是否可以在运行时为Java中的类合成新方法?是否有图书馆可以实现这一目标?
答案 0 :(得分:3)
进入已加载的课程?据我所知。
但是,您可能对生成新课程感兴趣。我看到两个选择:
public static void printTest() {
System.out.println("Hey!");
}
然后看一下字节码,看看ConstantPool中的哪个位置“嘿!”存储,然后获取方法的字节码,将其缓存到字节数组中,然后动态创建具有预定义字节+常量池(您之前检查过)的方法,并使用您的字符串修改constantpool。对于更复杂的方法,这会非常快速地变得非常棘手(注意:可以通过改变它调用的方法或者获取字段来完成同样的操作,例如更改为错误)
因为我认为没有任何好的选择,所以这些是你最好的选择
答案 1 :(得分:2)
除了字节码工程库之外,如果你有一个类的接口,你可以使用Java的Proxy
类。
使用界面:
public interface Foo {
void bar();
}
具体课程:
class FooImpl {
public void bar() {
System.out.println("foo bar");
}
}
要处理调用的方法,请使用InvocationHandler
:
class FooInvocationHandler implements InvocationHandler {
private Foo foo;
FooInvocationHandler(Foo foo) {
this.foo = foo;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
if (method.getName().equals("bar"))
System.out.println("foo me");
// return null if you don't want to invoke the method below
}
return method.invoke(foo, args); // Calls the original method
}
}
然后创建FooFactory
以使用Proxy
生成并包装FooImpl
个实例:
public class FooFactory {
public static Foo createFoo(...) {
Foo foo = new FooImpl(...);
foo = Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
new FooInvocationHandler(foo));
return foo;
}
}
这将包装FooImpl
对象,以便:
Foo foo = FooFactory.createFoo(...);
foo.bar();
打印:
foo me
foo bar
这是BCEL库的替代品,它可以做到这一点以及更多,包括从运行时信息生成类,但BCEL库不是本机的。 (Proxy
自1.3以来就在java.lang.reflect
所有内容。)