Javaのリフレクション
Classクラスのインスタンスの取得
リフレクション機能を使うためには、Class クラスのインスタンスを取得する必要がある。
reflectionTestパッケージのTestClassというクラスの「Class クラスのインスタンス」を取得するには以下の3の方法がある。
(1)クラスよりClassクラスのインスタンスの取得を取得する。
Class<?> aClass=TestClass.class;
(2)クラス名(文字列)より取得
try { Class<?> aClass = Class.forName("reflectionTest.TestClass"); ... } catch (ClassNotFoundException e) { e.printStackTrace(); }
(3)クラスのインスタンスより取得
TestClass testClass = new TestClass(); Class<?> aClass = testClass.getClass();
ここで「Class<?>」はClassクラスの総称型である。
Classクラスのインスタンスが取得できればこれを基に取得したクラスの様々な操作や情報の取得が可能になる。
クラスの情報の取得
以下のようなコードにてクラスに関する情報を取得して表示できる。
System.out.printf("Class: %s\n", aClass.getName()); System.out.printf("Package: %s\n", aClass.getPackage().getName()); System.out.printf("SimpleName: %s\n", aClass.getSimpleName()); System.out.printf("CanonicalName: %s\n", aClass.getCanonicalName());
スーパクラスおよびクラスの継承関係の取得
for(Class<?> superClass = aClass.getSuperclass(); superClass!=null;superClass = superClass.getSuperclass()) System.out.printf("Super Class: %s\n", superClass.getName());
以下の再帰メソッドにてインターフェースおよびインターフェースの継承関係を表示できる。
void printInterfaces(Class<?> aClass) { for(Class<?> aInterface : aClass.getInterfaces()){ System.out.printf("Interface: %s\n", aInterface.getName()); printInterfaces(aInterface); } }
インナークラスの列挙。
for(Class<?> innerClass : aClass.getClasses()){ System.out.printf("InnerClass: %s, %s\n", innerClass, Modifier.toString(innerClass.getModifiers())); }
クラスのアノテーション定義の列挙。
for(Annotation annotation : aClass.getDeclaredAnnotations()){ System.out.printf("Annotation: %s, %s\n", annotation); }
クラスのインスタンスの作成とコンストラクタ
クラスのインスタンスを生成するには以下のコードとなる。
Object instance; try { instance = aClass.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }
クラスのコンストラクタの列挙。
for(Constructor<?> constructor : aClass.getConstructors()){ System.out.printf("Constructor: %s, %s\n", constructor.toGenericString(), Modifier.toString(constructor.getModifiers())); }
クラスの引数なしコンストラクタを実行してクラスのインスタンスを生成。
Object instance; Constructor<?> cunstructor; try { cunstructor = aClass.getConstructor(); try { instance = cunstructor.newInstance(new Object[]{ new Integer(123), new String("hoge")}); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); }
引数あり(int型引数とString型引数の)コンストラクタを実行してクラスのインスタンスを生成。
Object instance; Constructor<?> cunstructor; try { cunstructor = aClass.getConstructor(int.class, String.class); try { instance = cunstructor.newInstance(123, "hoge"); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); }
フィールドの操作
フィールドの列挙。
for(Field field : aClass.getDeclaredFields()){ System.out.printf("Field: %s, %s\n", field.getName(), Modifier.toString(field.getModifiers())); }
フィールドの操作。
try { // インスタンスフィールド Field field; instance = aClass.newInstance(); field = aClass.getDeclaredField("instanceField"); field.set(instance, "bar"); String s = (String)field.get(instance); System.out.printf("instanceField : %s\n", s); // static フィールド field = aClass.getDeclaredField("staticField"); field.set(null, 88); int i = (Integer)field.get(null); System.out.printf("staticField : %d\n", i); // private フィールド field = aClass.getDeclaredField("prop2"); field.setAccessible(true); // privateメンバへのアクセスを許可 field.set(instance, "huga"); s = (String)field.get(instance); System.out.printf("prop2 : %s\n", s); } catch (Exception e) { e.printStackTrace(); }
メソッドの操作
メソッドの列挙。
for(Method method : aClass.getDeclaredMethods()){ System.out.printf("Method: %s, %s\n", method.getName(), Modifier.toString(method.getModifiers())); }
メソッドの操作。
Method method; try { // staticメソッド(引数なし) method = aClass.getMethod("staticMethod"); System.out.printf("TestClass.staticMethod() : %s\n", method.invoke(null)); // インスタンスメソッド(引数なし) instance = aClass.newInstance(); method = instance.getClass().getMethod("method1"); System.out.printf("testClass.method1() : %s\n", method.invoke(instance)); // インスタンスメソッド(引数あり) method = instance.getClass().getMethod("method2", String.class, int.class); System.out.printf("testClass.method2(\"fuga\", 555) : %s\n", method.invoke(instance, "huga", 555)); // インスタンスメソッド(private) method = instance.getClass().getDeclaredMethod("method3"); method.setAccessible(true); // privateメンバへのアクセスを許可 System.out.printf("testClass.method3() : %s\n", method.invoke(instance)); } catch (Exception e) { e.printStackTrace(); }
プロパティの操作
PropertyDescriptor propertyDescriptor; try { propertyDescriptor = new PropertyDescriptor("prop1", aClass); instance = aClass.newInstance(); //セッターメソッド操作 Method setterMethod = propertyDescriptor.getWriteMethod(); setterMethod.invoke(instance, -111); //ゲッターメソッド操作 Method getterMethod = propertyDescriptor.getReadMethod(); int i = (Integer) getterMethod.invoke(instance); System.out.println(i); } catch (Exception e) { e.printStackTrace(); }
サンプルに使用したソースコードと実行結果
動作確認に使用したコードと実行結果は以下のとおりである。
ReflectionTest.java》
package reflectionTest; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class ReflectionTest { public static void main(String args[]) { //Package.getPackage(name); Class<?> aClass; aClass=TestClass.class; PrintClassInfo(aClass); try { aClass = Class.forName("reflectionTest.TestClass"); PrintClassInfo(aClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } TestClass testClass = new TestClass(); aClass = testClass.getClass(); PrintClassInfo(aClass); Object instance; try { instance = aClass.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } Constructor<?> cunstructor; try { cunstructor = aClass.getConstructor(new Class[]{int.class,String.class}); //cunstructor = aClass.getConstructor(int.class, String.class); try { instance = cunstructor.newInstance(new Object[]{ new Integer(123), new String("hoge")}); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } // フィールド操作 try { // インスタンスフィールド Field field; instance = aClass.newInstance(); field = aClass.getDeclaredField("instanceField"); field.set(instance, "bar"); String s = (String)field.get(instance); System.out.printf("instanceField : %s\n", s); // static フィールド field = aClass.getDeclaredField("staticField"); field.set(null, 88); int i = (Integer)field.get(null); System.out.printf("staticField : %d\n", i); // private フィールド field = aClass.getDeclaredField("prop2"); field.setAccessible(true); // privateメンバへのアクセスを許可 field.set(instance, "huga"); s = (String)field.get(instance); System.out.printf("prop2 : %s\n", s); } catch (Exception e) { e.printStackTrace(); } // メソッド操作 Method method; try { // staticメソッド(引数なし) method = aClass.getMethod("staticMethod"); System.out.printf("TestClass.staticMethod() : %s\n", method.invoke(null)); // インスタンスメソッド(引数なし) instance = aClass.newInstance(); method = instance.getClass().getMethod("method1"); System.out.printf("testClass.method1() : %s\n", method.invoke(instance)); // インスタンスメソッド(引数あり) method = instance.getClass().getMethod("method2", String.class, int.class); System.out.printf("testClass.method2(\"fuga\", 555) : %s\n", method.invoke(instance, "huga", 555)); // インスタンスメソッド(private) method = instance.getClass().getDeclaredMethod("method3"); method.setAccessible(true); // privateメンバへのアクセスを許可 System.out.printf("testClass.method3() : %s\n", method.invoke(instance)); } catch (Exception e) { e.printStackTrace(); } // プロパティ操作 PropertyDescriptor propertyDescriptor; try { propertyDescriptor = new PropertyDescriptor("prop1", aClass); instance = aClass.newInstance(); //セッターメソッド操作 Method setterMethod = propertyDescriptor.getWriteMethod(); setterMethod.invoke(instance, -111); //ゲッターメソッド操作 Method getterMethod = propertyDescriptor.getReadMethod(); int i = (Integer) getterMethod.invoke(instance); System.out.println(i); } catch (Exception e) { e.printStackTrace(); } } static void PrintClassInfo(Class<?> aClass) { System.out.printf("Class: %s\n", aClass.getName()); System.out.printf("Package: %s\n", aClass.getPackage().getName()); System.out.printf("SimpleName: %s\n", aClass.getSimpleName()); System.out.printf("CanonicalName: %s\n", aClass.getCanonicalName()); for(Class<?> superClass = aClass.getSuperclass(); superClass!=null;superClass = superClass.getSuperclass()) System.out.printf("Super Class: %s\n", superClass.getName()); printInterfaces(aClass); for(Constructor<?> constructor : aClass.getConstructors()){ System.out.printf("Constructor: %s, %s\n", constructor.toGenericString(), Modifier.toString(constructor.getModifiers())); } for(Field field : aClass.getDeclaredFields()){ System.out.printf("Field: %s, %s\n", field.getName(), Modifier.toString(field.getModifiers())); } for(Method method : aClass.getDeclaredMethods()){ System.out.printf("Method: %s, %s\n", method.getName(), Modifier.toString(method.getModifiers())); } for(Annotation annotation : aClass.getDeclaredAnnotations()){ System.out.printf("Annotation: %s, %s\n", annotation); } for(Class<?> innerClass : aClass.getClasses()){ System.out.printf("InnerClass: %s, %s\n", innerClass, Modifier.toString(innerClass.getModifiers())); } } static void printInterfaces(Class<?> aClass) { for(Class<?> aInterface : aClass.getInterfaces()){ System.out.printf("Interface: %s\n", aInterface.getName()); printInterfaces(aInterface); } } }
《TestClass.java》
package reflectionTest; public class TestClass extends TestClassSuper implements ITestInterface1,ITestInterface2{ public class NestNestTestClass { } public static int staticField=33; public String instanceField="xxx"; public String method1 () { return prop2 + String.valueOf(prop1); } public String method2 (String s, int i) { return s + String.valueOf(i); } static public String staticMethod () { return TestClass.class.getName(); } private int method3 () { return 999; } public TestClass () { } public TestClass (int i, String s) { prop1=i; prop2=s; } private int prop1=99; private String prop2="abc"; public int getProp1() { return prop1; } public void setProp1(int prop1) { this.prop1 = prop1; } public String getProp2() { return prop2; } public void setProp2(String prop2) { this.prop2 = prop2; } }
《TestClassSuper.java》
package reflectionTest; public class TestClassSuper { }
《ITestInterface1.java》
package reflectionTest; public interface ITestInterface1 { }
《ITestInterface2.java》
package reflectionTest; public interface ITestInterface2 extends ITestInterface2Super{ }
《ITestInterface2Super.java》
package reflectionTest; public interface ITestInterface2Super { }
プログラムの実行結果
Class: reflectionTest.TestClass Package: reflectionTest SimpleName: TestClass CanonicalName: reflectionTest.TestClass Super Class: reflectionTest.TestClassSuper Super Class: java.lang.Object Interface: reflectionTest.ITestInterface1 Interface: reflectionTest.ITestInterface2 Interface: reflectionTest.ITestInterface2Super Constructor: public reflectionTest.TestClass(int,java.lang.String), public Constructor: public reflectionTest.TestClass(), public Field: staticField, public static Field: instanceField, public Field: prop1, private Field: prop2, private Method: staticMethod, public static Method: method1, public Method: method2, public Method: method3, private Method: getProp1, public Method: setProp1, public Method: getProp2, public Method: setProp2, public InnerClass: class reflectionTest.TestClass$NestNestTestClass, public Class: reflectionTest.TestClass Package: reflectionTest SimpleName: TestClass CanonicalName: reflectionTest.TestClass Super Class: reflectionTest.TestClassSuper Super Class: java.lang.Object Interface: reflectionTest.ITestInterface1 Interface: reflectionTest.ITestInterface2 Interface: reflectionTest.ITestInterface2Super Constructor: public reflectionTest.TestClass(int,java.lang.String), public Constructor: public reflectionTest.TestClass(), public Field: staticField, public static Field: instanceField, public Field: prop1, private Field: prop2, private Method: staticMethod, public static Method: method1, public Method: method2, public Method: method3, private Method: getProp1, public Method: setProp1, public Method: getProp2, public Method: setProp2, public InnerClass: class reflectionTest.TestClass$NestNestTestClass, public Class: reflectionTest.TestClass Package: reflectionTest SimpleName: TestClass CanonicalName: reflectionTest.TestClass Super Class: reflectionTest.TestClassSuper Super Class: java.lang.Object Interface: reflectionTest.ITestInterface1 Interface: reflectionTest.ITestInterface2 Interface: reflectionTest.ITestInterface2Super Constructor: public reflectionTest.TestClass(int,java.lang.String), public Constructor: public reflectionTest.TestClass(), public Field: staticField, public static Field: instanceField, public Field: prop1, private Field: prop2, private Method: staticMethod, public static Method: method1, public Method: method2, public Method: method3, private Method: getProp1, public Method: setProp1, public Method: getProp2, public Method: setProp2, public InnerClass: class reflectionTest.TestClass$NestNestTestClass, public instanceField : bar staticField : 88 prop2 : huga TestClass.staticMethod() : reflectionTest.TestClass testClass.method1() : abc99 testClass.method2("fuga", 555) : huga555 testClass.method3() : 999 -111