1. ホーム
  2. java

[解決済み] 実行時に、Javaアプリケーションでベースクラスを拡張しているすべてのクラスを検索する

2022-04-26 18:16:58

質問

このようなことをしたいのですが。

List<Animal> animals = new ArrayList<Animal>();

for( Class c: list_of_all_classes_available_to_my_app() )
   if (c is Animal)
      animals.add( new c() );

そこで、アプリケーションのユニバースにあるすべてのクラスを見て、Animalの子孫にあたるものを見つけたら、その型の新しいオブジェクトを作成してリストに追加したいのです。 これによって、リストを更新することなく、機能を追加することができる。 次のようなことを避けることができます。

List<Animal> animals = new ArrayList<Animal>();
animals.add( new Dog() );
animals.add( new Cat() );
animals.add( new Donkey() );
...

上記の方法で、Animalを継承した新しいクラスを作るだけで、自動的にピックアップされるようになった。

UPDATE: 10/16/2008 9:00 a.m.(太平洋標準時)。

この質問には、たくさんの素晴らしい回答が寄せられています。 回答や調査から、私が本当にやりたいことは、Javaでは不可能であることがわかりました。 ddimitrovのServiceLoaderメカニズムなど、動作するアプローチもありますが、私が望むものには非常に重く、単に問題をJavaコードから外部設定ファイルに移動させるだけだと考えています。 19年5月10日更新 (11年後!) 現在では、@IvanNik の記事によると、これを助けることができるいくつかのライブラリがあります。 回答 org.reflections(オルグ・リフレクションズ が良さそうです。また クラスグラフ から、@Luke Hutchison の 回答 は面白そうですね。回答の中にも、さらにいくつかの可能性があります。

私が欲しいものを述べる別の方法:私のAnimalクラスの静的関数は、Animalを継承するすべてのクラスを見つけ、インスタンス化します--さらなる設定/コーディングなしで。 もし設定が必要なら、Animal クラスでインスタンス化したほうがいいかもしれません。 Javaプログラムは.classファイルの緩やかな連合体なので、そういうものなのだと理解しています。

興味深いことに、どうやらこれは かなり些細なこと をC#で作成しました。

どのように解決するのですか?

私は org.reflections(オルグ・リフレクションズ :

Reflections reflections = new Reflections("com.mycompany");    
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);

別の例

public static void main(String[] args) throws IllegalAccessException, InstantiationException {
    Reflections reflections = new Reflections("java.util");
    Set<Class<? extends List>> classes = reflections.getSubTypesOf(java.util.List.class);
    for (Class<? extends List> aClass : classes) {
        System.out.println(aClass.getName());
        if(aClass == ArrayList.class) {
            List list = aClass.newInstance();
            list.add("test");
            System.out.println(list.getClass().getName() + ": " + list.size());
        }
    }
}