2012-03-27 4 views
8

私はいくつかの値を持つStringを持っています。特定のメソッドを呼び出すパッケージ内のすべてのクラスを繰り返し処理したい場合は、メソッドによって返された値がMy Stringの値と等しい場合は、そのクラスのオブジェクトを作成します。Reflectionを使ってパッケージ内のすべてのクラスを反復することはできますか?

私はこれを動的なやり方で行いたいので、このパッケージにクラスを追加すると自動的に反復されます。

これは可能ですか? もしそうでなければ、私がしたいことをする方法がありますか?


私は何かを期待していました。

for(Class clazz: SomeClass.listClasses("org.package")){ 
    //code here 
} 
+0

「このパッケージにクラスを追加する」とは何ですか?どのようにそれはJavaプロセスのクラスパスに入るのですか? –

+0

@Jeffrey私はReflectionについて読んでいましたが、私はこれが唯一の方法だと思っていますが、私はReflectionについて何も知らないのです。私はそのパッケージにある各クラスの検証を追加する "普通の方法"を試みましたが、拡張可能ではないので、この方法は望ましくありません。 –

+0

@MiserableVariable開発時に、パッケージに新しいクラスを追加します(すべてのクラスはDocumentという抽象クラスを拡張します)。 –

答えて

8

いいえ、これは完全に信頼できる方法ではありません。しかし、多くの場合、実装するのが現実的かもしれません。

Javaクラスローダーの柔軟性により、特定のパッケージの下で定義されたクラスは、実行時に認識されないことがあります(例えば、クラスをネットワーク上からロードすることによってオンザフライで定義する特殊なクラスローダーを考えたり、それらをアドホックにコンパイルする)。そのため、パッケージ内のクラスを一覧表示できる標準のJava APIはありません。

しかし実際には、すべてのクラスとJARファイルのクラスパスを検索し、完全修飾クラス名のコレクションを作成し、必要に応じてそれらを検索することで、いくつかのトリックを行うことができます。前の段落で説明したようにアクティブなクラスローダーが動作しないことが確実であれば、この戦略はうまくいきます。たとえば、(Java擬似コード):

Map<String, Set<String>> classesInPackage = new HashMap(); 
for (String entry : eachClasspathEntry()) { 
    if (isClassFile(entry)) { 
    String packageName = getPackageName(entry); 
    if (!classesInPackage.containsKey(packageName)) { 
     classesInPackage.put(packageName, new HashSet<String>()); 
    } 
    classesInPackage.get(packageName).add(getClassName(entry)); 
    } else if (isJarOrZipFile(entry)) { 
    // Do the same for each JAR/ZIP file entry... 
    } 
} 
classesInPackage.get("com.foo.bar"); // => Set<String> of each class... 
+0

しかし、カスタムクラスローダーは、少なくとも理論的には可能です。 –

+0

@MiserableVariable:空のクラスを定義するクラスのバイトコードを指定されたクラス名で返すことによって、 'defineClass(String)'メソッドを実装するカスタムクラスローダを作成したとします。これは完全に有効なクラスローダーであり、定義できるすべてのクラスをリストする方法はありません。 – maerics

+0

はい、一般的に問題は解決できません。特定の狭い状況では違います。フォルダ名 'plugins'のすべての.classファイルをチェックし、' register'メソッドを持つすべてのクラスでインスタンスを作成することができます。 –

1

ありますが、一般的な解決策ではありません。コードをパッケージ化し、JVMを特定の方法で呼び出す必要があります。具体的には、計装エージェントを作成し、java.lang.instrument.Instrumentation.getAllLoadedClasses()と呼ぶ必要があります。

パッケージdocumentation for java.lang.instrumentには、エージェントの作成およびインスタンス化の方法に関する詳細が多数あります。

+0

彼はロードされたクラスだけを望んでいませんが、クラスパス内のフォルダにドロップされた新しいクラスファイル(恐らく) –

+0

@MiserableVariableロードされたいクラスは開発時に定義されています。ランタイムで。 –

2

私は自分の問題と思われるものを解決するには2つの方法があると考えることができますが、どちらもパッケージ内のすべてのクラスを真に反復することはできません。

1つは、特定のメソッドを呼び出す必要があるクラスをリストする別のファイルを作成することです。これは実装が非常に簡単です。ファイルを作成する作業があるかもしれませんが、それは自動化できます。

2番目のオプションは、いくつかのよく知られている場所、たとえば単一のフォルダまたはフォルダのセットなどで.classファイルを探し、クラス名を推測して読み込みます。これが単純な開発プロセスであれば、単一のパッケージからのクラスファイルはおそらく単一のディレクトリにあります。