2009-05-19 16 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中聲明的方法,不能從超類型繼承。因此,如有必要,遍歷具體的類層次結構。其次,SecurityManager可以阻止使用setAccessible方法。所以,它可能需要運行爲PrivilegedAction(使用AccessControllerSubject)。

+1

當我在過去完成這項工作時,我在調用方法後也調用了method.setAccessible(false),但我不知道這是否有必要。 – shsteimer 2009-05-19 01:53:43

32

使用getDeclaredMethod()獲取私有方法對象,然後使用method.setAccessible()來允許實際調用它。

+7

接受的答案是實際完成調用。 – 2009-05-19 00:21:47

+0

在我自己的例子中(http://stackoverflow.com/a/15612040/257233)如果我不調用`setAccessible(true)`,我會得到`java.lang.StackOverflowError`。 – 2013-03-25 10:11:33

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; 
    } 

接受的參數是物鏡,方法名,參數的計數接受和參數。例如

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");