2016-05-05 9 views
1

私はMethodを受け取り、後で呼び出すためにそれを保存するAPIを持っています。それを呼び出すために私はsetAccessible(true)をしなければならない。私がそれをする前に、私は守備的なコピーを作りたいと思っています。しかしどうですか?java.lang.reflect.Methodをコピーするにはどうしたらいいですか?

私は

method.getDeclaringClass() 
     .getDeclaredMethod(method.getName(), method.getParameterTypes()); 

考えるが、それは必ずしもバックブリッジ法(または2つの方法が同じ名前/パラメータの型が異なる戻り値の型を持つ他のケースの存在下で、私に同じ方法を与えることはありません)。

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() 
+0

は、なぜあなたは守備のコピーを作成したいですか? –

+0

どのような条件の下で、方法は避けたい方法で変わるでしょうか? – hexafraction

+0

@SotiriosDelimanolis:コンストラクタの引数を変更するのは、一般的には驚くべきことです。クライアントが後に 'setAccessible(false)'を呼び出す状況を避けるためです。 –

答えて

1

あなたはもともと提案何と指定されたオブジェクトに対して、このMethodを比較

を述べMethod#equals(Object)の契約に依存する必要があります。 のオブジェクトが同じ場合は、trueを返します。 2つの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."); 
} 
関連する問題