Saturday, March 1, 2014

In Java, is it possible to override methods in a class that you create using reflection? For example, say I have the following class:
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;
    }
}
And in one 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 a way to override a method in this same manner using reflection? Maybe something like this? :
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 of doing this, or an external library that could help? I am looking for way to add listeners to a setter method in order to change binded values.
share|improve this question
1 
You need a dynamic code generation library, such as javassist. –  Marko Topolnik Dec 8 '12 at 17:20
add comment

3 Answers

No, it's not possible in the way of your example.
In your example, the Java compiler will create two separate classes:
MyObject.class
MyObject$1.class
The latter being the one with the overridden method. In this case, it's an anonymous inner class (SeeJava tutorial documentation)
But there is more complex solution involving bytecode weaving libraries. Libraries such as cglib, asm, javassist etc. give you a facility to dynamically create new classes at runtime and load them.
Javassist has a tutorial on how to add methods to classes at runtime. It should be possible to adapt it to add/override the method, something like this:
CtClass origClazz = ClassPool.getDefault().get("org.example.MyObject");
CtClass subClass = pool.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();
share|improve this answer

3 comments: