2009-11-10 24 views
6

我希望能夠做的是加載一組類,可能都在同一個文件夾中。所有這些實現相同的接口,並且是相同的類,然後在我的代碼中,我希望能夠在這些類上調用函數。Java:動態加載同一類的多個版本

+0

這是不可能不玩遊戲的自定義類加載器(甚至可能不可能)。也許如果你解釋了你想要完成的事情,你會得到更多的幫助。 – 2009-11-10 05:07:15

+0

OSGI看起來很有趣,但也許我錯誤地接近了這個問題。 從一般意義上講,這是我試圖完成的。我有一個運行遊戲機制的遊戲Oware的外殼。它要求其他班級通過向他們發送遊戲狀態並返回一個動作來進行動作。 我想有認可各自包含不同的代碼的文件夾中,可能有許多這樣的。然後shell將在所有找到的AI上運行循環賽,並輸出哪些AI根據哪個AI獲勝。 – JonLeah 2009-11-10 05:23:08

回答

5

選擇,看來你要定義一個遊戲界面,然後插入在許多AI實現中,可能由.properties文件配置。這是API接口的相當標準的用法。

您定義了一個EngineInterface,它提供了一種接受遊戲狀態並返回移動的方法。然後定義所有實現EngineInterface的多個類。您的驅動程序讀取屬性文件以獲取實現類的名稱,使用Class.forName()將它們實例化並將它們存儲在列表和/或映射中。然後,當驅動程序獲取請求時,它會依次調用每個實現並跟蹤結果。

1
  1. 如果你可以使用OSGI,它的那樣簡單 搶購手指!在oSGI中,您可以使用 具有相同的 類的多個版本。你所做的是有相同的 與不同版本的捆綁。

  2. 否則,您仍然可以編寫自定義類加載器來讀取這兩個類。一種做法就是這樣。您編寫兩個ClassLoaders,其中一個加載一個類的版本,另一個加載該類的另一個版本。現在根據需要選擇classloader1或classloader2來加載類。所以現在你可以在內存中同時加載同一個類的多個版本。

注:確保這其實你想要做的是,有可能是在你的問題來的其他方式。

+0

我可以擁有osgi嗎? – 2009-11-10 05:08:50

+0

@jason ......我沒聽懂你:) – 2009-11-10 06:27:46

+5

「那樣簡單搶購手指」 ......這是關於OSGi的一個大膽的聲明。 – Thilo 2009-11-11 03:32:31

1

我知道它不支持你是什麼後OSGI的唯一框架:

alt text http://blog.springsource.com/wp-content/uploads/2009/01/network.png

它的網絡模型,本文 「Exposing the boot classpath in OSGi」 中所描述的,並允許

網絡模型的一個副作用(或目標)是類型隔離或類版本控制:相同類的多個版本可以很好地共存於同一個VM中,因爲ea一個是加載到自己的網絡,自己的空間。

看到這個tutorial的開始和EOF OSGi框架(如EquinoxKnoplerfishApache Felix)根據你回答我的問題

2

你有沒有嘗試過這樣的:

class Move; // some data type that is able to represent the AI's move. 

interface AI { 

    Move getMove(GameState state); 
}; 

AIOne implements AI; 
AITwo implements AI; 

每個類將實施其自己的算法生成一個舉動,但會被調用,但通過常用的方法稱爲

2

它可以做你想做的與OSGI,但你可以使用自定義類加載器。這個想法是,你必須爲要加載的每個類的版本創建一個類加載器。Here你可以找到一個很好的解釋。

但我覺得你真正需要解決你的問題是基於接口,如由吉姆·加里森和戴夫大號德萊尼描述的東西...

0

它可以使用動態類加載來完成。它不是加載不同版本的類,而是加載超類或接口的不同子類。

最重要的步驟是:

(1)使用的Class.forName(...)通過名稱加載一個類。該課程必須在課程路徑中。

(2)使用aClass.newInstance()來實例化對象。如果構造函數不需要參數,這很容易。

以下代碼應該爲您提供一些想法。它不處理你必須做的異常。

class Context { 
    void moveUp(); 
    void moveDown(); 
    ... 
} 

interface AI { 
    void action(Context con); 
} 

public class Game { 
    public Game() { 
     Context aContext = new Context(); 
     String[] aAIClsNames = this.getAIClassNames("ai.list"); 
     AI[]  aAIs  = this.loadAI(aAIClsNames); 
     this.run(aAIs); 
    } 
    String[] getAIClassNames(String pAIClassListFile) { 
     // .. Load the file containning the AI-class file names 
    } 
    AI[] loadAI(String[] pAIClsNames) { 
     AI[] AIs = new AI[pAIClsNames.length]; 
     for(int i = 0; i < pAIClsNames.length; i++) { 
      String aAIClsName  = pAIClsNames[i]; 

      // (1) Get the class by name 
      Class<? extends AI> aAICls = Class.forName(aAIClsName); 

      // (2) Notice the cast as all of class in the list must implements AI 
      AIs[i] = (AI)aAICls.newInstance(); 
     } 
     return AIs; 
    } 
    void run(AI[] pAIs) { 
     // ... 
    } 
} 

希望這會有所幫助。

0

Jim的回覆非常好 - 您將要使用的類命名,並且它們都符合通用API。然而,給出的解決方案假定類已經在應用程序的類路徑中可用。您可能希望能夠在稍後添加更多實現,例如應用程序安裝後。

如果是這樣的話,那麼你可能需要使用自定義類加載器。例如,您可以允許用戶將jar文件放在特定文件夾的某處,並將實現的類名添加到屬性文件中。然後,您需要一個自定義類加載器,而不是從該文件夾內的jar中加載類,並且您將使用該類加載器加載類(例如,使用Class.forName(className,classLoader))。

事實上,如果你有每個jar文件一個類加載器,你就可以有多個類與整個jar文件相同的名稱,如類加載器定義的類名邊界。這幾乎是OSGI正在做的。

下面是從罐子與加載類的一些代碼:

http://sourceforge.net/projects/jcloader/ http://www.javaworld.com/javatips/jw-javatip70.html