Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I override methods in Java when I create an Object via reflection?

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.

like image 596
Phil Avatar asked Dec 08 '12 17:12

Phil


People also ask

Can we override object method in Java?

Because of this, all Java classes inherit methods from Object . Half of these methods are final and cannot be overridden. However, the other methods in Object can be and are overridden, often incorrectly. This article explains why it's important to implement these methods correctly and then explains how to do so.

Can we create object using reflection in Java?

We can use newInstance() method on the constructor object to instantiate a new instance of the class. Since we use reflection when we don't have the classes information at compile time, we can assign it to Object and then further use reflection to access it's fields and invoke it's methods.

Which method is used to get methods using reflection?

The getConstructors() method is used to get the public constructors of the class to which an object belongs. The getMethods() method is used to get the public methods of the class to which an object belongs. We can invoke a method through reflection if we know its name and parameter types.

How do I stop reflection in Java?

Yes, reflection is slow, and it creates fragile code when used in this way. If you want to avoid the if statement, you should use polymorphism.


2 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 (See Java 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 = 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();
like image 115
mhaller Avatar answered Sep 17 '22 15:09

mhaller


If you're returning an object of an interface type, you can use Proxy.newProxyInstance to get an instance of an interface that dynamically sends method invocations to an InvocationHandler object which you can write to do whatever custom behavior you want.

like image 44
Louis Wasserman Avatar answered Sep 21 '22 15:09

Louis Wasserman