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.
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.
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.
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.
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.
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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With