2012-06-28 41 views
6
沒有做「正常方式」

我有一個例外,當我執行此代碼:方法工作在反射但在Java

p7 = new PKCS7(p7byte); 
... 
SignerInfo si = p7.getSignerInfos()[0]; 
String name = si.getDigestAlgorithmId().getName(); 

,異常是:

Exception in thread "main" java.lang.NoSuchMethodError: sun/security/pkcs/SignerInfo.getDigestAlgorithmId()Lsun/security/x509/AlgorithmId; 
     at reflex.Reflex.testPKCS7(Reflex.java:151) 
     at reflex.Reflex.main(Reflex.java:43) 

這在IBM機器上執行代碼時執行代碼異常,而在Windows機器上執行該代碼時,它會正常工作。

研究這個,我發現si.getDigestAlgoritmId()的返回類對於IBM機器是不同的。對於IBM的Java,它是com.ibm.security.x509.AlgorithmId,對於java6它是sun.security.x509.AlgorithmId。這兩個類都有一個getName()方法。

但最奇怪的是,如果我通過反射調用該方法,異常不會出現,並且它在兩種環境中都能正常工作。有人可以回答爲什麼它以這種方式工作嗎?

我認爲解決方案是用反射來做,但我想知道爲什麼反射它的工作原理和它沒有的正常方式。主要是爲了避免將來出現類似的錯誤。

在此先感謝並對我的英語不好。

編輯: 反射調用:

try{ 
    Class clase = si.getClass(); 
    Method metodo = clase.getMethod("getDigestAlgorithmId"); 
    Object result = metodo.invoke(si,null); 
    System.out.println("Result.class=" + result.getClass().getName()); 
    System.out.println("Result=" + result); 
}catch(Exception e){...} 
+1

如果您使用反射來添加如何調用該方法,那將會很好。 –

回答

2

SignerInfo.getDigestAlgoritmId()在這兩個的Java版本不同的聲明。如果你用一個聲明來編譯你的類,它就不會與另一個聲明一起工作。該類型存儲在您的.class文件中,並且必須在運行時匹配。

如果使用反射,則編譯時不需要聲明getDigestAlgoritmId。它將與任何聲明一起工作,只要它符合您指定的名稱和參數即可。

小心反思。 sun.security.x509.AlgorithmId似乎不屬於公共Java API的一部分。版本和供應商可能有所不同。這兩個僅在回報類型上有所不同。誰知道其他Java實現中的差異。如果可能的話,堅持使用官方的Java API。