我有一些像这样的代码:
Object doMethod(Method m, Object... args) throws Exception {
Object obj = m.getDeclaringClass().getConstructor().newInstance();
return m.invoke(obj, args);
}
我使用的代码有点复杂,但这就是它的想法。要调用doMethod
我会这样做:
Method m = MyClass.class.getMethod("myMethod", String.class);
String result = (String)doMethod(m, "Hello");
这对我来说很好(可变数量的参数和所有)。 让我感到烦恼的是调用者String
必要的强制转换。由于myMethod
声明它返回String
,我想{{1}足够聪明,将其返回类型更改为doMethod
。有没有办法使用Java泛型来完成这样的事情?
String
答案 0 :(得分:4)
当然,
@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);
}
演员将是你试图分配给它的任何东西,但我认为大多数人会认为它是可疑的。
答案 1 :(得分:3)
我希望Method已被参数化以捕获返回类型。您可以通过使用自己的MethodEx包装Method来自己做到这一点......这样做可以让您提供一些非常漂亮的外观......
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
}
}
这只是一个起点 - 您可以在MethodEx上使用工厂方法进行大量的前期验证,以确保方法是公开的等等。
最后,如果你正在缓存Method实例等并处理动态加载的类,这也是一个很好的机会来防御性地引入弱引用(对于方法和返回类型),所以你不必像小心在整个代码中挂起整个类加载器。
答案 2 :(得分:1)
你可以尝试
public <T> T doMethod(Method m, Class<T> clazz, Object... args);
虽然它会将演员阵容移动到例程本身。一般来说,你想要做的事情听起来并不是一个好习惯。反思本身会产生一些性能开销,但也许不值得关注?