Получить экземпляр всех подклассов базового класса в пакете - PullRequest
1 голос
/ 03 марта 2011

Предположим, что исходный код моего приложения для Android упакован следующим образом:

src/
   my/
      app/
         Module.java
         ModuleManager.java
         module/
            ModuleA.java
            ModuleB.java

, где Module:

public abstract class Module {
    public abstract void run();
}

, ModuleA и ModuleB extends Module:

public class ModuleA extends Module {
    @Override
    public void run() { /* do something */  }
}

и ModuleManager имеет несколько вспомогательных методов, среди которых один для извлечения всех Module s:

public class ModuleManager {

    private final static List<Module> modules;
    static {
        List<Module> tmp= new ArrayList<Module>();
        tmp.add(new ModuleA());
        tmp.add(new ModuleB());
        modules= Collections.unmodifiableList(tmp);
    }

    public static List<Module> getModules(){
        return modules;
    }
}

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

Я пробовал несколькими способамиРешения на основе отражений , подобные этому , которые включают использование ClassLoader::getResource(String path) для извлечения каждого файла .class внутри пакета module , но он всегда возвращает пустое перечисление.Я узнал, что это связано с различием между виртуальной машиной Dalvik и Java SE, а также оптимизированной упаковкой файлов .class в classes.dex .Затем я попытался импортировать apk приложения из / data / app / с помощью DexClassLoader или PathClassLoader и безуспешно попробовал метод getResource() снова.Во всяком случае, я думаю, что это не правильное направление, и, возможно, этот материал уже был хакерским / испорченным в Java, и это было бы еще больше в Android.

Не могли бы вы предложить мне способ сделать это?

Большое спасибо.

Ответы [ 3 ]

2 голосов
/ 03 марта 2011

Один из способов сделать это в скрипте сборки, после компиляции, но перед вызовом dex для создания classes.dex, запустить небольшой скрипт, чтобы получить имена классов в папке модулей и записать его, чтобы сказать файл application.properties для чтенияfrom (или strings.xml в ресурсах).

Недостаток этого метода в том, что вы запрашиваете не чистый Java-метод, а преимущество в том, что он будет работать для 2 или 10 подклассов.Надеюсь, это поможет.

1 голос
/ 04 марта 2011

Другое решение может заключаться в использовании соглашения об именах для имен классов и извлечении их всех по одному с помощью Class.forName(className).В приведенном мной примере, если я знаю, что все модули названы последовательно как ModuleA, ModuleB, ModuleC и т. Д., Я могу получить их все, начиная с ModuleA и продолжая до тех пор, пока не произойдет сбой Class.forName("ModuleX").Если бы допускались пропуски, но количество модулей было ограничено (и очень мало), можно было бы провести исчерпывающий поиск по всему диапазону.

Конечно, это можно применять в очень немногих случаях и за счетчитаемости имени класса.

1 голос
/ 03 марта 2011

Что делать, если вы добавляете XML или Properties с классами модуля и динамически создаете их ... это может выглядеть примерно так

<modules>
    <module>
    my.app.module.ModuleA
    </module>
    <module>
    my.app.module.ModuleB
    </module>
</modules>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...