2012-03-21 49 views
2

我有一個ClassLoader,它從源文件加載由JavaCompiler編譯的類。 但是,當我更改源文件,保存並重新編譯它時,ClassLoader仍然加載該類的第一個版本。Java類加載器:加載兩次相同的類

ClassLoader cl = Thread.currentThread().getContextClassLoader(); 
    Class<?> compiledClass = cl.loadClass(stringClass); 

我在想什麼?像newInstance什麼的?

回答

10

類加載器無法替換已經加載的類。 loadClass將返回現有Class實例的參考。

你將不得不實例化一個新的類加載器並使用它來加載新的類。然後,如果你想「替換」這個類,你必須把這個類加載器扔掉,並創建另一個新類。


在回答您的評論(縣):這樣做

ClassLoader cl = new UrlClassLoader(new URL[]{pathToClassAsUrl}); 
Class<?> compiledClass = cl.loadClass(stringClass); 

這個類加載器將使用「默認的代理父類加載器」,你必須照顧,類(由它確定完全限定的類名)尚未加載,並且不能由該父類加載器加載。所以「pathToClassAsUrl」不應該在類路徑中!

+0

如何在我的方法中替換或刪除ClassLoader? – ctekk 2012-03-21 12:48:47

+0

另外:如果我寫一個自定義ClassLoader,它會工作嗎? – ctekk 2012-03-21 12:57:54

+0

謝謝你,我在這裏發現了你的評論的一個很好的解釋:http://www.exampledepot.com/egs/java.lang/reloadclass.html – ctekk 2012-03-26 09:36:40

1

您每次都必須加載一個新的ClassLoader,或者每次給這個類指定一個不同的名稱並通過接口訪問它。

例如

interface MyWorker { 
    public void work(); 
} 

class Worker1 implement MyWorker { 
    public void work() { /* code */ } 
} 

class Worker2 implement MyWorker { 
    public void work() { /* different code */ } 
} 
+0

如何每次使用相同的方法加載新的ClassLoader? – ctekk 2012-03-21 13:24:19

+0

你可以創建一個新的ClassLoader(),你可以通過調用defineClass來觸發它來加載類。 – 2012-03-21 18:49:37

+0

新的Classloader()不能像這樣啓動。 – ctekk 2012-03-22 09:07:10

0

我認爲這個問題可能比其他答案的建議更基礎。類加載器很可能會加載與您認爲不同的文件。爲了測試這個理論,刪除.class文件(不要重新編譯你的.java源文件)並運行你的代碼。你應該得到一個例外。

如果你沒有得到異常,那麼很顯然,類加載器正在加載一個不同於你認爲的那個.class文件。因此,搜索具有相同名稱的另一個.class文件的位置。刪除該.class文件並重試。繼續嘗試,直到找到實際加載的.class文件。一旦你這樣做,你可以重新編譯你的代碼,並手動將類文件放在正確的目錄中。

+0

但上面的答案表明,一旦加載類,類加載器不會再從文件加載它。這似乎是適當的行爲。我也想到了。 – ctekk 2012-03-22 09:06:17