Java: динамически загружать несколько версий одного класса

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

7 ответов


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

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


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

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;

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


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

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


единственная структура, которую я знаю, которая поддерживает то, что вам нужно, - это OSGI:

alt текст http://blog.springsource.com/wp-content/uploads/2009/01/network.png

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

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

посмотреть этот учебник для начала и выберите на EOF OSGi Framework (например,Эквинокс, Knoplerfish или Апач Феликс)


  1. Если вы можете использовать OSGI, его так же просто, как щелкает пальцем! В oSGI вы можете несколько verssions же класс. Все, что вам сделать, это же связки с различными версиями.

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

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


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

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

(1) Использовать Класс.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) {
        // ...
    }
}

надеюсь, что это помогает.


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

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

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

вот код, относящийся к классам загрузки из банок:

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