Java: динамически загружать несколько версий одного класса - PullRequest
6 голосов
/ 10 ноября 2009

То, что я хотел бы сделать, это загрузить набор классов, вероятно, все в одной папке. Все они реализуют один и тот же интерфейс и являются одним и тем же классом, поэтому в моем коде я хотел бы иметь возможность вызывать функции этих классов.

Ответы [ 7 ]

5 голосов
/ 10 ноября 2009

Судя по вашему ответу на мой вопрос, вы, похоже, хотите определить интерфейс игры, а затем подключить любое количество реализаций ИИ, возможно, настроенных из файла .properties. Это довольно стандартное использование интерфейса API.

Вы определяете EngineInterface, предоставляющий метод, который принимает состояние игры и возвращает ход. Затем вы определяете несколько классов, которые все реализуют EngineInterface. Ваш драйвер читает файл свойств, чтобы получить имена классов реализации, создает их экземпляры с помощью Class.forName () и сохраняет их в списке и / или карте. Затем, когда драйвер получает запросы, он по очереди вызывает каждую реализацию и отслеживает результаты.

2 голосов
/ 10 ноября 2009

С OSGI можно делать все, что угодно, но вы также можете использовать собственный загрузчик классов. Идея состоит в том, что вам нужно создать загрузчик классов для каждой версии класса, который вы хотите загрузить. Здесь вы можете найти хорошее объяснение.

Но я думаю, что вам действительно нужно решить вашу проблему - это что-то, основанное на интерфейсах, подобных описанным Джимом Гаррисоном или Дейвом Л Делани ...

2 голосов
/ 10 ноября 2009

Вы пробовали что-то вроде:

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;

Каждый класс будет реализовывать свой собственный алгоритм генерации хода, но будет вызываться, но вызываться общим методом

1 голос
/ 10 ноября 2009

Единственный известный мне фреймворк, поддерживающий то, что вы ищете, это OSGI :

alt text

Его сетевая модель, описанная в этой статье « Отображение пути загрузки в OSGi », допускает, что

Одним из побочных эффектов (или целей) сетевой модели является изоляция типа или управление версиями классов: несколько версий одного и того же класса могут прекрасно сосуществовать внутри одной виртуальной машины, поскольку каждая из них загружается в свою собственную сеть, свое собственное пространство.

См. Этот учебник для начала и выберите на основе OSGI Framework (например, Equinox , Knoplerfish или Apache Felix )

1 голос
/ 10 ноября 2009
  1. Если вы можете использовать OSGI, это так же просто, как щелкнув пальцем! В ОСГИ вы можете иметь несколько версий одного и того же учебный класс. Все, что вы делаете, это то же самое связки с разными версиями.

  2. В противном случае вы все равно можете написать свой собственный загрузчик классов, который читает оба класса. Один из способов сделать это будет так. Вы пишете два ClassLoaders, один из которых загружает одну версию класса, а другой загружает другую версию класса. Теперь, основываясь на необходимости, вы выбираете classloader1 или classloader2 для загрузки класса. Так что теперь вы можете также загрузить в память несколько версий одного и того же класса одновременно.

Примечание: Убедитесь, что это именно то, что вы хотите сделать, могут быть другие способы решения вашей проблемы.

0 голосов
/ 09 марта 2011

Хороший ответ Джима - вы называете классы, которые хотите использовать, и все они соответствуют общему API. Однако данное решение предполагает, что все классы уже доступны в пути к классам приложения. Возможно, вы захотите иметь возможность добавить больше реализаций позже, например, после установки приложения.

Если это так, то вам, вероятно, придется использовать собственный загрузчик классов. Например, вы могли бы позволить людям помещать файлы jar в определенную папку где-нибудь и добавлять имена классов реализаций в файл свойств. Затем вам потребуется пользовательский загрузчик классов, который может загружать классы из jar-файлов внутри этой папки, и вы будете использовать этот загрузчик классов для загрузки классов (например, используя Class.forName (className, classLoader)).

Фактически, если у вас есть файл загрузчика классов для каждого файла JAR, вы можете иметь несколько классов с одинаковыми именами в файлах JAR, так как загрузчик классов определяет границы имен классов. Это в значительной степени то, что делает OSGI.

Вот некоторый код, относящийся к загрузке классов из jars:

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

0 голосов
/ 10 ноября 2009

Это можно сделать с помощью динамической загрузки классов. Это не класс загрузки другой версии, а разные подклассы суперкласса или интерфейса.

Важными шагами являются:

(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];

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

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

Надеюсь, это поможет.

...