2013-06-21 94 views
1

我在使用Java中的反射時遇到了一些麻煩。我試圖保存一個數據結構的方法,但得到一個錯誤。該錯誤是Java,反射,獲取類的方法

java.lang.NoSuchMethodException: cs671.eval.SerialList.add(java.lang.Integer, java.lang.String)

的方法,在這種情況下,我想要得到的是一個SerialList是採取了類似和對象作爲參數add方法。

structType = "cs671.eval.SerialList",keyType = "java.lang.Integer"valType = "java.lang.String"是從文件讀入的字符串。

Class dataClass = null, comparableClass = null, objectClass = null; 

try{ // create data structure 
    dataClass = Class.forName(structType); 
    comparableClass = Class.forName(keyType); 
    objectClass = Class.forName(valType); 
} 
catch(ClassNotFoundException e){} 

java.lang.Object structObj = null; 

try{ // Create a data structure object 
    structObj = dataClass.newInstance(); 
} 
catch(Exception e){} 
Method m = null; 
try{ // Attempt to get add method for the data structure 
    m = dataClass.getMethod("add", comparableClass, objectClass); // This is where it fails 
} 
catch(Exception e){} 

基本上我試圖讓與該會得到傳遞到該方法的正確課程的權利數據結構正確的方法,但我不知道怎麼告訴實現getMethod方法,這些類(可比的類和對象類)是正確的。

在此先感謝!

補充:這裏的SerialList的add方法簽名 public void add(java.lang.Comparable, java.lang.Object)

+0

'cs671.eval.SerialList.add'的簽名是什麼? – Polygnome

+0

您是否嘗試過運行Class.getMethods並打印名稱/參數類型列表?如果例如SerialList擴展了ArrayList ,那麼Add方法實際上就是add(int,Object)。 – Sbodd

+0

@Polygnome:Addes簽名發佈。 –

回答

5

你是說 -

的方法,在這種情況下,我想要得到的是一個SerialList的add方法以可比較的對象作爲其參數。

但通過類 - java.lang.Integer,java.lang.String


只是注意 - 只有公共方法是可見的getMethod()非公衆,你將不得不使用getDeclaredMethod()來代替。

+0

這些類,Integer和String是在後面的代碼中傳入add方法的對象的類。我通過讀取類名來獲取它們,創建它們的類實例,並將這些類實例傳入getMethod。儘管getMethod期待一個Comparable和Object。我需要知道如何使用這兩個類來告訴getMethod它們是正確的,因爲Integer將是一個可比較的對象,而String將是一個Object Object。 –

+0

'Comparable.class'和'Object.class'。 –

+0

我不想將這些內容硬編碼,因爲稍後可以用不同的簽名檢索不同的方法。 –

1

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getMethod%28java.lang.String,%20java.lang.Class...%29

要找到一個C類匹配的方法:如果是C聲明瞭指定名稱只有一個公共方法和完全相同的形式參數類型,這是該方法的體現。如果在C中找到多於一個這樣的方法,並且這些方法中的一個具有比其他方法更具體的返回類型,則反映該方法;否則其中一種方法是任意選擇的。

=>您需要通過java.lang.Comparable.class & java.lang.Object.class

0

道歉較早提供錯誤的答案。根據您的意見,您似乎試圖通過避免提供該方法簽名中所需的特定參數類型來獲取方法。

如果我的理解是正確的,那麼您應該使用Class#getMethods()並檢查返回的Method[]您的方法。考慮這樣的框架代碼:

Method[] methods = dataClass.getMethods(); 
boolean matched = false; 
// find a matching method by name 
for (Method method: methods) { 
    Class<?>[] parameterTypes = method.getParameterTypes(); 
    if ("add".equals(method.getName()) && parameterTypes.length == 2) { 
     // method is your target method 
     // however you'll need more strict checks if there can be another add method 
     // in your class with 2 different parameter types 
    } 
} 
0

至於其他的答案已經指出,使用getMethod()你需要知道和使用方法的實際宣佈正式參數您正試圖取回。但是,如果由於某種原因,您在編譯時不知道形式參數,那麼您可以遍歷該類中的所有方法,直到找到適合您參數的方法(或找到最具體的方法適合你的參數)。

在apache commons bean utils中已經寫入了這樣的功能,特別是在org.apache.commons.beanutils.MethodUtils.invokeMethod(...)MethodUtils.getMatchingAccessibleMethod(...)中。

上述方法的源代碼可以在線輕鬆查看here