How do I override methods in Java when I create objects through reflection?
In Java, can methods in classes created using reflection be overridden? For example, say I have the following classes:
public class MyObject { public String foo,bar; public MyObject(String foo) { this.foo = foo; this.bar = foo + "bar"; } public void setBar(String bar) { this.bar = bar; } }
In a class, I want to create it directly and override its setbar method as follows:
MyObject obj = new MyObject("something") { @Override public void setBar(String bar) { this.bar = this.foo; } };
Is there any way to use reflection to cover the method in the same way? Maybe so?:
Class<?> _class = Class.forName("com.example.MyObject"); Constructor<?> _constructor = _class.getConstructor(new Class<?>[]{String.class}); Method m = _class.getmethod("setBar",new Class<?>[]{String.class}); Object obj = _constructor.newInstance("Foo String") { m = new Method(new Class<?>[]{String.class}) { System.out.println("Foobar"); } };
If not, are there other ways to do this, or can an external library help? I'm looking for ways to add listeners to a setter method to change the value of the binding
Solution
No, your example is impossible
In your example, the java compiler will create two separate classes:
MyObject.class MyObject$1.class
The latter is the covered method In this case, this is an anonymous inner class (see Java Tutorial documentation)
But there are more complex solutions involving bytecode weaving libraries Libraries such as cglib, ASM and javassist can provide you with the ability to dynamically create new classes and load them at runtime
Javassist has a tutorial on how to add methods to classes at runtime It should be possible to adjust it to add / override the method as follows:
CtClass origClazz = ClassPool.getDefault().get("org.example.MyObject"); CtClass subClass = ClassPool.getDefault().makeClass(cls.getName() + "New",origClazz); CtMethod m = CtNewMethod.make( "public void setBar(String bar) { this.bar = bar; }",subClass ); subClass .addMethod(m); Class clazz = cc.toClass();