2009-05-19 26 views
107

XMLとリフレクションを使用して別のクラスにObjectを返すクラスがあります。プライベートメソッドを呼び出す方法はありますか?

通常、これらのオブジェクトは外部オブジェクトのサブフィールドですが、ときどき生成したいものです。私はこのようなものを試しましたが、役に立たないものです。私はそれはJavaがあなたに反射のためのprivateメソッドにアクセスすることを許可しないためだと思います。

Element node = outerNode.item(0); 
String methodName = node.getAttribute("method"); 
String objectName = node.getAttribute("object"); 

if ("SomeObject".equals(objectName)) 
    object = someObject; 
else 
    object = this; 

method = object.getClass().getMethod(methodName, (Class[]) null); 

提供方法がprivateであれば、それはNoSuchMethodExceptionで失敗します。メソッドpublicを作成するか、それを派生させる別のクラスを作成して解決できます。

私はちょうどリフレクションによってprivateメソッドにアクセスする方法があるかどうか疑問に思っていました。

答えて

233

リフレクションでプライベートメソッドを呼び出すことができます。投稿されたコードの最後のビットを変更する:

Method method = object.getClass().getDeclaredMethod(methodName); 
method.setAccessible(true); 
Object r = method.invoke(object); 

警告にはいくつかの注意点があります。まず、getDeclaredMethodは、現在のClassで宣言されたメソッドのみを検索し、スーパータイプから継承しません。したがって、必要に応じて具体的なクラス階層をトラバースしてください。第2に、SecurityManagerは、setAccessibleメソッドの使用を防ぐことができます。したがって、PrivilegedActionAccessControllerまたはSubjectを使用)として実行する必要があります。

+1

私は過去にこれをやったときに、メソッドを呼び出した後にmethod.setAccessible(false)も呼びましたが、これが必要かどうかはわかりません。 – shsteimer

+12

いいえ、ユーザー補助機能を設定すると、そのインスタンスにのみ適用されます。特定のMethodオブジェクトをコントロールから逃さない限り、安全です。 – erickson

+5

私は絶対にあなたが仲良しの愛を反転させます。恐ろしい答え+悪いコード==あまりにも悪い日。 – droope

32

getDeclaredMethod()を使用してプライベートメソッドオブジェクトを取得し、method.setAccessible()を使用して実際に呼び出すことができます。

+7

として呼び出すことができ受け入れ答えは実際には完了です。 –

+0

私自身の例(http://stackoverflow.com/a/15612040/257233) 'setAccessible(true)'を呼び出さないと、 'java.lang.StackOverflowError'を取得します。 –

21

方法は、非プリミティブデータを受け入れる場合、以下の方法は、任意のクラスのプライベートメソッドを呼び出すために使用することができ、次に入力:受け付け

public static Object genericInvokMethod(Object obj, String methodName, 
      int paramCount, Object... params) { 
     Method method; 
     Object requiredObj = null; 
     Object[] parameters = new Object[paramCount]; 
     Class<?>[] classArray = new Class<?>[paramCount]; 
     for (int i = 0; i < paramCount; i++) { 
      parameters[i] = params[i]; 
      classArray[i] = params[i].getClass(); 
     } 
     try { 
      method = obj.getClass().getDeclaredMethod(methodName, classArray); 
      method.setAccessible(true); 
      requiredObj = method.invoke(obj, params); 
     } catch (NoSuchMethodException e) { 
      e.printStackTrace(); 
     } catch (IllegalArgumentException e) { 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } catch (InvocationTargetException e) { 
      e.printStackTrace(); 
     } 

     return requiredObj; 
    } 

パラメータOBJ、methodNameであり、パラメータの数が受け入れられパラメータ。例えば

public class Test { 
private String concatString(String a, String b) { 
    return (a+b); 
} 
} 

方法concatStringが

Test t = new Test(); 
    String str = (String) genericInvokMethod(t, "concatString", 2, "Hello", "Mr.x"); 
+5

なぜ_paramCount_が必要ですか? * params.length *を使うことはできませんか? –

関連する問題