Combining Java generics and their reflection to avoid casting

I have a code like this:

Object doMethod(Method m, Object... args) throws Exception {
    Object obj = m.getDeclaringClass().getConstructor().newInstance();
    return m.invoke(obj, args);
}

The code I use is a little more complicated, but the idea is it. To call doMethod, I am doing something like this:

Method m = MyClass.class.getMethod("myMethod", String.class);
String result = (String)doMethod(m, "Hello");

This works fine for me (a variable number of arguments and all). The thing that annoys me is the necessary cast in Stringthe caller. . Since it myMethoddeclares that it returns String, I would like it to doMethodbe smart enough to change its return type should also be String. Is there a way to use Java generics to do something like this?

String result = doMethod(m, "Hello");
int result2 = doMethod(m2, "other", "args");
+3
source share
3 answers

Of course,

@SuppressWarnings("unchecked")
<T> T doMethod(Method m, Class<T> returnType, Object Args ...) {
    Object obj = m.getDeclaringClass().getConstructor().newInstance();
    return (T) m.invoke(obj, args);
}

String result = doMethod(m, m.getReturnType(), "Hello");

, , , - :)

, returnType, , . , :

@SuppressWarnings("unchecked")
<T> T doMethod(Method m, Object Args ...) {
    Object obj = m.getDeclaringClass().getConstructor().newInstance();
    return (T) m.invoke(obj, args);
}

, , , .

+4

, . , MethodEx... ...

public class MethodEx<T> {
  private final Method _method;
  private final Class<T> _returnType;

  public MethodEx(Method method, Class<T> returnType) {
    _method = method;
    _returnType = returnType;
  }

  public T invoke(Object object, Object... args) throws InvocationTargetException {
    try {
      return _returnType.cast(_method.invoke(object, args));
    }
    // good opportunity to hide/wrap other exceptions if your 
    // usecases don't really encounter them
  }
}

. factory ExEx, , , ..

, Method .. , ( ), .

+3

You can try

public <T> T doMethod(Method m, Class<T> clazz, Object... args);

Although he moves the cast into the procedure itself. In general, what you are trying to do is not like good practice. Reflection itself imposes certain overheads, but perhaps this is not a concern?

+1
source

All Articles