2010-07-08 58 views
27

在我當前的項目中,我覺得需要使用反射在Java中創建一種模擬回調系統。不過,我有問題讓我的反思真正起作用。有過錯的代碼如下:Java:NoSuchMethodException當方法明確存在時

public Callback(Object parentObj, String methodName, Class<?>...parameters) 
{ 
    if(parentObj == null) 
     throw new IllegalArgumentException("parentObj cannot be null", new NullPointerException()); 

    Class<?> clazz = parentObj.getClass(); 

    // Trace debugging, see output 
    for(Method m : clazz.getDeclaredMethods()) 
     if(m.getName().equals("myMethod")) System.out.println (m); 

    try { this.method = clazz.getMethod(methodName, parameters); } 
    catch(NoSuchMethodException nsme) { nsme.printStackTrace(); } // Exception caught 
    catch(SecurityException se) { se.printStackTrace(); } 

    this.parentObj = parentObj; 
    this.parameters = parameters; 
} 

當我構建Callback對象,我使用的語法如下:

new Callback(this, "myMethod", boolean.class) 

當我嘗試創建我的僞回調,它擊中NoSuchMethodException抓塊。我在上面包含了一些跟蹤調試,以顯示我的某個方法失敗的輸出。輸出:

private void my.package.MyClass.myMethod(boolean) 
java.lang.NoSuchMethodException: my.package.MyClass.myMethod(boolean) 
    at java.lang.Class.getMethod(Class.java:1605) 
    at my.package.other.Callback.<init>(Callback.java:63) 

我無法找出問題出來,所以我開始狩獵,沒有多大用處。我能找到的最好的是提到編譯JAR和運行時之間的版本衝突。但是,MyJar.jar/META-INF/MANIFEST.MF包含Created-By: 1.6.0_02 (Sun Microsystems Inc.)。我的IDE正在運行C:\Program Files\Java\jdk1.6.0_02\bin\javac.exe來編譯我的項目。我使用C:\Program Files\Java\jdk1.6.0_02\bin\java.exe來運行我的JAR。

我不知道爲什麼Class.getMethod聲稱該方法不存在,但Class.getMethods似乎沒有發現它的問題。幫幫我? :(

+1

這就是爲什麼你不依賴於反射,這是最不可靠的。 – quantumSoup 2010-07-08 02:27:59

+0

我不會說這是不可靠的,但它可能是複雜和低效的。 – 2010-07-08 02:30:22

+1

它肯定比你的編譯器證明是正確的東西不可靠。 :-) – 2010-07-08 02:37:08

回答

86

你的方法是私有的,但是getMethod()只返回公共方法。您需要使用getDeclaredMethod()

+0

Yes!這可以解決問題而不會強迫我使用公共方法。謝謝! – 2010-07-08 02:51:20

+3

3年後...這對我來說很有意義。儘管我開始閱讀http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getMethod(java.lang.String,java.lang。類......),他們沒有提到這些信息。也許你看過代碼?對你有好處。 +1 – Mzn 2013-05-09 11:51:29

+0

將我的頭撞在牆上2個小時。謝啦 ! – 2015-11-23 05:22:47

0

的版本問題,可以在編譯時與運行時引起NoSuchMethodException是不是編譯器版本之間的差異。這是(在你的情況下)的版本差異MyClass

既然你使用反射你的問題可能無關版本,雖然,當然,不會解釋getMethodgetDeclaredMethods之間不同的行爲,因爲你正在運行他們對同一個類的實例,因此一個版本的區別是不是真的有可能。

您確定參數符合您的實際方法嗎?

4

的Javadoc getMethod不明確,但它看起來像它可能拋出一個NoSuchMethodException對於不公開的方法,你的方法是私有的。

+2

是的,就是這樣。您的建議讓我翻閱Class的源代碼。 'getMethod'調用(私有)'getMethod0'。'getMethod0'調用'privateGetDeclaredMethods(true)',其中'true'爲''publicOnly'「 – 2010-07-08 02:49:04

1

您需要參數列表絕對正確,才能使呼叫成功。

我發現在做反射時微小的步驟很重要,因爲編譯器沒有幫助。寫一個小片段,它實際上調用了這個特定情況下想要的方法,然後當它有效時,將其推廣到此處的框架中。我會專注於傳遞的參數。

相關問題