Reputation: 215
I have dozens of functions which are alternatives to each other. They take an input and return an output, but in each case the output is slightly different. All of them are embedded in a single wrapper class.
I want to invoke them by passing the method name as a string. I would also like to avoid manually maintaining a huge list of unneeded if statements:
if(methodName.equals("method1")
return method1(argument);
...
else if(methodName.equals("method176")
return method176(argument);
So far I've figured out how to call the methods dynamically but only if the methods are static:
try {
method = MyMainClass.class.getDeclaredMethod(methodName, MyArgumentClass.class);
ResultClass result = (ResultClass)method.invoke(null, myArgument);
return result;
}
catch(Exception e)
{
e.printStackTrace();
System.exit(1);
return null;
}
Is it possible to this for non-static methods, and invoke the functions on class instances instead of the static class?
Upvotes: 4
Views: 4985
Reputation: 44969
Yes. Using Java reflection just pass the instance to invoke it on as the first argument to the invoke
method.
Read: http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#invoke
try {
MyArgumentClass argument = new MyArgumentClass();
MyMainClass instance = new MyMainClass(argument);
method = MyMainClass.class.getDeclaredMethod(methodName, MyArgumentClass.class);
ResultClass result = (ResultClass) method.invoke(instance, myArgument);
return result;
}
catch(Exception e)
{
e.printStackTrace();
System.exit(1);
return null;
}
As pointed out in the other answers, this is not the best approach to your problem. You should implement the Strategy pattern like so:
interface MyOperation{
public ResultClass execute(MyArgumentClass argument);
}
public class Method1 implements MyOperation {
public ResultClass execute(MyArgumentClass argument){
....
}
}
public class Method176 implements MyOperation {
public ResultClass execute(MyArgumentClass argument){
....
}
}
public class DoIt{
public ResultClass doIt(MyOperation method, MyArgumentClass argument){
return method.doIt(argument);
}
}
Upvotes: 5
Reputation: 134
Yes it is possible to do so but you have to use the Java Reflection package java.lang.reflect.* Have a look at the "Invoke methods by name" section in this link http://java.sun.com/developer/technicalArticles/ALT/Reflection/
Upvotes: 1
Reputation: 8451
Get an instance of your Method, which is retrieved from the Class like you're doing, then call Method.invoke() with the instance of the class you wish to call the method on.
You may also use some of the beans available from Spring to accomplish something similar, if you're interested in going that route.
Upvotes: 1
Reputation: 96454
Yes, it's possible. Pass in the object you want to invoke the method on as the first argument to the invoke
call. Call getClass
on the object to get the class to use.
Upvotes: 1
Reputation: 4113
When possible, better avoid reflection. Seems like your problem can be solved with better design using the Strategy pattern.
Upvotes: 5