4

我正在尋找一個轉換器來從一個普通的Java代碼製作反射式Java代碼。我這樣做是爲了防止像NoClassDefFoundError這樣的異常(我想依賴於一個類,但是如果我使用的庫沒有該依賴類,我希望Java簡單地忽略代碼)。尋找一個代碼轉換器將普通的Java代碼轉換爲反射式代碼

我希望轉換器是這樣的:

初始代碼:

com.foo.MyClass myClass = new com.foo.MyClass() 
myClass.meth1(); 

轉換後:

Object myClass = Class.forName("com.foo.MyClass").newInstance(); 
myClass.getMethods("meth1").invoke(myClass); 
+0

嘗試的Class.forName(「com.foo.MyClass」)。的newInstance(),捕獲它可能拋出的異常,如果它確實拋出,只是不實例com.foo.MyClass? – mwittrock 2010-08-10 13:44:17

+0

感謝您的回答。我的錯!我認爲Sun Java一旦看到一個不存在的「導入」就會拋出異常。看來它只在到達無效行時才拋出異常。 您可以請您的評論作爲答案,以便我可以接受它。 – Mohsen 2010-08-11 06:55:07

回答

1

你應該儘量避免在Java代碼中儘可能使用反射您可以。您可以使用其他方法,例如@mwittrock建議的方法,以避免獲得那些NoClassDefFoundError

您可能可以使用反射來解決問題,但是您可能會在設計中引入新問題。考慮性能成本以及反射代碼的冗長性。

核心反射設施是 最初設計用於 基於組件的應用程序構建 工具......有跡象表明, 需要反思幾個 sophisiticated應用。例子包括 類瀏覽器,對象督察, 代碼分析工具,並解釋 嵌入式系統......如果您有任何疑問 ,是否你的應用程序 屬於這些類別之一,它 可能不會。

Joshua Bloch,「Effective Java」,2nd Edition。

1

這可能是一種技術上可行的方法,但像其他海報一樣,我強烈建議您考慮這是否是解決問題的正確方法(並且您已經問過如何實施此解決方案而不是如何解決您的問題原來的問題,所以我不能告訴你,如果你在正確的軌道上或不)。

您是否有興趣選擇性地取決於圖書館,但不強迫您的客戶提供它?根據你的構建系統,這並不難完成。例如,Maven允許您指定一個依賴關係,如<scope>optional</scope>,它允許您針對它編譯代碼,但不包括它作爲傳遞依賴項。這就是說,確實有可能可以選擇性地依賴某些庫,並且如果它們不可用,則採取替代路線。根據我的經驗,這很容易通過隱藏界面背後的細節來完成。

作爲示例,我有一個ProfilingAdvisor接口,它可以與AspectJ方面一起使用,以剖析我用自定義標註標記的方法。我有一個名爲SimpleProfilingAdvisor的接口的基本實現,它沒有外部依賴關係。我有一個更詳細的實現,它使用Java Simon庫來獲取更多信息,稱爲SimonProfilingAdvisor。

如果客戶選擇包含Java Simon庫,他們會得到「更好」的實現。如果他們選擇不這樣做,那麼將實施「基礎」方法(在你的情況下可能是什麼都不做)。

我的代碼總是工作到接口,ProfilingAdvisor,但實例化這種類型的實例變量的時候,我必須確定可選西蒙庫是否在類路徑:

private ProfilingAdvisor advisor; 
    /* ... */ 
    try { 
     Class.forName("org.javasimon.SimonManager"); 
     this.advisor = new SimonProfilingAdvisor(); 
    } catch (ClassNotFoundException classNotFoundException) { 
     this.advisor = new SimpleProfilingAdvisor(); 
    } 

的最後一點。雖然你可以用反射來確定一個類的存在,但是我不能想到你在實例化之後通過反射方法訪問它而獲得的任何東西,而且你有效地繞過了編譯器的能力,你在方法名稱上的拼寫等。

至少,你應該使用一個構建系統,它允許你在編譯時編譯一個庫,但不一定包括它在你的發行版中(例如Maven) 。