リフレクションを使用して属性を取得する
クラスには、これまで見てきたもの以外にもさまざまな要素が含まれています。例えば、変数はどうでしょうか。リフレクションを使用すれば、このような要素についても詳細な出力を得られます。次に示すのは、Fieldクラスを使用した例です。
import java.lang.reflect.*;
public class DumpFields {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Field[] fields = c.getFields();
for (int i = 0; i < fields.length; i++)
System.out.println(fields[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
このコードをコンパイルし、Employeeを引数として実行すると、
java DumpFields Employee
次のような出力が得られます。
public java.lang.String Employee.empNum public java.lang.String Employee.empName
この結果には、このクラスに属するすべてのフィールドと属性が列挙されています。
リフレクションを使用してコンストラクタを取得する
Constructorクラスを使用すると、使用可能な各種のコンストラクタとその使用方法を詳しく知ることができます。
import java.lang.reflect.*;
public class DumpConstructors {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Constructor[] constructor = c.getConstructors();
for (int i = 0; i < constructor.length; i++)
{
System.out.println(constructor[i].toString());
//To print the parameter types
Class pvec[] = constructor[i].getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #" + j + " "
+ pvec[j]);
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
このコードをコンパイルし、Employeeを引数として実行すると、
javac DumpConstructors Employee
結果は、次のようになります。
public Employee(java.lang.String,java.lang.String) param #0 class java.lang.String param #1 class java.lang.String public Employee()
この結果を分析してみると、Employeeクラスには2つのコンストラクタがあることが分かります。最初のコンストラクタは、パラメータを持つコンストラクタです(パラメータの型も分かります)。2番目は引数をとらないコンストラクタで、特に説明の必要もないでしょう。
リフレクションを使用して実行時にクラスメソッドを実行する
実行時に使用したいクラスがあると仮定しましょう。次のコードは、このクラスを実行時にロードして、目的のメソッドを実行する方法を示しています。ここで前提となっているのは、このメソッドの名前がsetPropertiesであり、java.util.Properties型の引数を1つとるということです。
Class newClass = null;
Method getInstanceMethod = null;
Properties prop = new Properties();
prop.put("argName", "argValue");
try
{
Object obj = newClass.newInstance();
getInstanceMethod = newClass.getMethod("setProperties",
new Class[]{new Properties().getClass()});
}
catch (Exception ex)
{
//Exception in loading Class:" + ex.getMessage();
}
このような柔軟性により、IDE開発者は極めて簡単にJavaをサポート対象プログラミング言語に加えることができます。
ここまでは、JavaリフレクションAPIを使用する利点を説明してきましたが、リフレクションの欠点についても理解しておく必要があります。例えば、プロセスがよくわかっていないのにリフレクションをデバッグに使用すると、大変な目に遭います。リフレクションは、使用可能な他の方法と比較してメリットが多いと判断した場合にだけ、特定の問題の解決に使用してください。
参考資料
- 『Using Java Reflection』(Sun Developer Network)
- 『Trail: The Reflection API』(Sun Developer Network)
