Reputation: 105
I know using reflection we can call method at run time. I have one requirement obj.getMethod1().getMethod2().getMethod3()
to be called at run time. Method Name will be know only during run time. Number of methods also differ during run time. sometimes it can be obj.getMethod1().getMethod2()
.
Currently I am handling through array as below
obj=initialObj;
for(i=0;i<arrayValue.length;i++){
tempobj=obj.getClass.getMethod(arrayValue[i])// arrayValue contains method name
obj=tempobj;
}
Is there any other better way of doing this?
Upvotes: 1
Views: 1397
Reputation: 18245
This is util class, that contains common methods:
public final class ReflectionUtils {
public static <T> T invokeMethod(Object obj, String name, Class<?>[] types, Object... values) throws Throwable {
try {
Method method = getMethod(obj.getClass(), name, types);
method.setAccessible(true);
return (T)method.invoke(obj, values);
} catch(InvocationTargetException e) {
throw e.getTargetException();
}
}
private static Method getMethod(Class<?> cls, String name, Class<?>... types) throws NoSuchMethodException {
Method method = null;
while (method == null && cls != null) {
try {
method = cls.getDeclaredMethod(name, types);
} catch(NoSuchMethodException ignored) {
cls = cls.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException();
}
return method;
}
}
This is how to call obj.getMethod1().getMethod2().getMethod3()
:
public static Object invokeMethods(Object obj, String... methodNames) throws Throwable {
for (String methodName : methodNames)
obj = ReflectionUtils.invokeMethod(obj, methodName, null);
return obj;
}
And client code could look like this:
Object res = invokeMethods(obj, "getMethod1", "getMethod2", "getMethod2");
Upvotes: 0
Reputation: 271175
Assuming your methods don't have parameters, you can do this:
public static Object callChainedMethods(Object obj, String[] methodNames) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<?> type = obj.getClass();
Object objectOnWhichToCallMethod = obj;
for (String methodName : methodNames) {
Method m = type.getMethod(methodName);
objectOnWhichToCallMethod = m.invoke(objectOnWhichToCallMethod);
type = objectOnWhichToCallMethod.getClass();
}
return objectOnWhichToCallMethod;
}
If you don't need to return the final return value:
public static void callChainedMethods(Object obj, String[] methodNames) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<?> type = obj.getClass();
Object objectOnWhichToCallMethod = obj;
for (String methodName : methodNames) {
Method m = type.getMethod(methodName);
objectOnWhichToCallMethod = m.invoke(objectOnWhichToCallMethod);
type = objectOnWhichToCallMethod.getClass();
}
}
For example:
String[] methods = {"toString", "getClass", "getClass"};
System.out.println(callChainedMethods((Integer)10, methods));
// prints "class java.lang.Class"
// because it is calling ((Integer)10).toString().getClass().getClass()
Upvotes: 1