我有一个使用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/

10-10 22:36