我有一个使用Method
并将其存储以供以后调用的API。为了调用它,我必须做setAccessible(true)
。在此之前,我想做一个防御性的副本。但是如何?
我想到了
method.getDeclaringClass()
.getDeclaredMethod(method.getName(), method.getParameterTypes());
但这并不一定会在存在桥接方法的情况下为我提供相同的方法(或者在其他情况下,两个方法具有相同的名称/参数类型但返回类型不同)。
我可以遍历
method.getDeclaringClass().getDeclaredMethod()
并寻找完全匹配的内容,但这似乎效率不高。一个示例说明了防御性副本可能很好的原因:
Method method = ...;
// Does setAccessible(true)
MyInvoker invoker = new MyInvoker(method);
// Sometime later, the user uses the same Method rather than re-retrieving it
method.setAccessible(true);
method.invoke(...);
method.setAccessible(false);
// Oops, now MyInvoker is broken
getDeclaredMethod()
返回不同方法的示例:interface Iface {
Object get();
}
class Impl implements Iface {
@Override
public String get() {
return "foo";
}
}
for (Method method : Impl.class.getDeclaredMethods()) {
System.out.println(method);
System.out.println(copy(method));
System.out.println();
}
private Method copy(Method method) {
try {
return method.getDeclaringClass()
.getDeclaredMethod(method.getName(), method.getParameterTypes());
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
对我来说,这打印:
public java.lang.String com.maluuba.api.Impl.get()
public java.lang.String com.maluuba.api.Impl.get()
public java.lang.Object com.maluuba.api.Impl.get()
public java.lang.String com.maluuba.api.Impl.get()
最佳答案
您必须按照您最初的建议去做,并依赖Method#equals(Object)
的合同,其中指出
将此Method
与指定对象进行比较。如果返回true
对象是相同的。如果两个Method
是相同的
由相同的类声明,并具有相同的名称和形式参数
类型和返回类型。
因此,您将无法使用getDeclaredMethod(String, Object...)
方法。您必须对Method[]
返回的getDeclaredMethods()
进行数组查找。例如,
private Method copy(Method method) {
Class<?> clazz = method.getDeclaringClass();
for (Method declaredMethod : clazz.getDeclaredMethods()) {
if (declaredMethod.equals(method)) {
return declaredMethod; // return the new one
}
}
throw new RuntimeException("This should not happen.");
}
关于java - 如何复制java.lang.reflect.Method?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37056931/