JavaのリフレクションAPIでコンストラクタ取得、インスタンス生成
JavaのリフレクションAPIでコンストラクタ取得、インスタンス生成を試してみたメモです。
前回に引き続き、JavaのリフレクションAPIを利用して、
コンストラクタ取得、インスタンス生成を試してみました。
java.lang.reflect.Constructor
JavaのリフレクションAPIを利用することで、メタデータにアクセスできます。
java.lang.reflect.Constructorクラスを利用してコンストラクタ取得、インスタンス生成を試してみたいと思います。
テスト用クラス
Mavenプロジェクトを作成し、pom.xmlはjunitとhamcrestだけdependencyに追加しました。
pom.xml
<dependencies> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-all</artifactId> <version>1.3</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit-dep</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies>
テスト対象のクラスは下記のようなクラスを作りました。
ReflectConstructorExample.java
package reflect; public class ReflectConstructorExample { private String name; private int age; private int num; public ReflectConstructorExample() { } protected ReflectConstructorExample(String name) { this.name = name; } ReflectConstructorExample(String name, int age) { this.name = name; this.age = age; } private ReflectConstructorExample(int num) { this.num = num; } }
public、protected、修飾子なし、private
のアクセス修飾子でそれぞれコンストラクタを作成しました。
Constructorオブジェクト
Constructorオブジェクトを取得するためのメソッドは下記です。
すべてClassクラスのメソッドです。
メソッド | 戻り値 | 取得可能なアクセス修飾子 |
---|---|---|
getConstructor | Constructor |
public |
getConstructors | Constructor[] | public |
getDeclaredConstructor | Constructor |
すべて |
getDeclaredConstructors | Constructor[] | すべて |
getConstructor()
getConstructor()では、指定したクラスのコンストラクタが取得できます。
取得できるのはpublicコンストラクタのみです。
引数にはコンストラクタへの引数の型を指定します。
// 引数なしのコンストラクタ Constructor cons = ReflectConstructorExample.class.getConstructor(); // Stringを引数に取るコンストラクタ Constructor cons = ReflectConstructorExample.class.getConstructor(String.class);
テストコード。
public static class getConstructorの確認 { @Test public void getConstructorでpublicコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(); int mod = cons.getModifiers(); assertThat(mod, is(Modifier.PUBLIC)); } @Test(expected = NoSuchMethodException.class) public void getConstructorでprotectedコンストラクタが取得できないこと() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(String.class); } @Test(expected = NoSuchMethodException.class) public void getConstructorでdefaultコンストラクタが取得できないこと() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(String.class, String.class); } @Test(expected = NoSuchMethodException.class) public void getConstructorでprivateコンストラクタが取得できないこと() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(int.class); } }
getConstructors()
getConstructors()では、指定したクラスのコンストラクタがConstructorクラスの配列で取得できます。
取得できるのはpublicコンストラクタのみです。
テストコード。
public static class getConstructorsの確認 { @Test public void getConstructorsでコンストラクタオブジェクトが取得できること() throws Exception { Class clazz = ReflectConstructorExample.class; Constructor[] cons = clazz.getConstructors(); Constructor[] expected = { clazz.getConstructor() }; assertThat(cons, is(arrayContainingInAnyOrder(expected))); } }
getDeclaredConstructor()
getDeclaredConstructor()では、getConstructor()と同様にコンストラクタが取得できますが、
getConstructor()と異なり、すべてのアクセス修飾子(public、protected、デフォルト、private)のコンストラクタが取得できます。
// publicコンストラクタ Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(); // protectedコンストラクタ Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(String.class); // defaultコンストラクタ Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(String.class, int.class); // privateコンストラクタ Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(int.class);
テストコード。
public static class getDeclaredConstructorの確認 { @Test public void getDeclaredConstructorでpublicコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(); int mod = cons.getModifiers(); assertThat(mod, is(Modifier.PUBLIC)); } @Test public void getDeclaredConstructorでprotectedコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(String.class); int mod = cons.getModifiers(); assertThat(mod, is(Modifier.PROTECTED)); } @Test public void getDeclaredConstructorでdefaultコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(String.class, int.class); int mod = cons.getModifiers(); assertThat(mod, is(0)); } @Test public void getDeclaredConstructorでprivateコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(int.class); int mod = cons.getModifiers(); assertThat(mod, is(Modifier.PRIVATE)); } }
getDeclaredConstructors()
getDeclaredConstructors()では、getConstructors()同様にConstructorクラスの配列で取得できますが、
getConstructors()と異なり、すべてのアクセス修飾子(public、protected、デフォルト、private)のコンストラクタが取得できます。
テストコード。
public static class getDeclaredConstructorsの確認 { @Test public void getDeclaredConstructorsでコンストラクタオブジェクトが取得できること() throws Exception { Class clazz = ReflectConstructorExample.class; Constructor[] cons = clazz.getDeclaredConstructors(); Constructor[] expected = { clazz.getDeclaredConstructor(), clazz.getDeclaredConstructor(String.class), clazz.getDeclaredConstructor(String.class, int.class), clazz.getDeclaredConstructor(int.class) }; assertThat(cons, is(arrayContainingInAnyOrder(expected))); } }
Constructorクラス
コンストラクタ情報取得
Constructorクラスのメソッドを利用してコンストラクタの情報が取得できます。
Constructor cons = ReflectConstructorExample.class.getConstructor(); // コンストラクタを宣言するクラスを取得 Class clazz = cons.getDeclaringClass(); // コンストラクタの名前取得 String name = cons.getName();
テストコード。
public static class Constructorクラスでコンストラクタ情報取得 { @Test public void getDeclaringClassでコンストラクタを宣言するクラスが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(); Class clazz = cons.getDeclaringClass(); assertThat(clazz, is(equalTo(ReflectConstructorExample.class))); } @Test public void getNameでコンストラクタの名前が取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(); String name = cons.getName(); assertThat(name, is("reflect.ReflectConstructorExample")); } }
コンストラクタを利用したインスタンス生成
ConstructorクラスのnewInstance()メソッドで、インスタンスを生成できます。
引数にはコンストラクタの要求する引数を指定します。
Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; // 引数なしのコンストラクタでインスタンス生成 ReflectConstructorExample ref = clazz.getConstructor().newInstance(); // Stringを引数に取るコンストラクタでインスタンス生成 ReflectConstructorExample ref = clazz.getDeclaredConstructor(String.class).newInstance("pro");
テストコード。
public static class コンストラクタを利用したインスタンス生成確認 { @Test public void publicコンストラクタでのインスタンス生成() throws Exception { Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; ReflectConstructorExample ref = clazz.getConstructor().newInstance(); assertThat(ref, is(instanceOf(ReflectConstructorExample.class))); } @Test public void protectedコンストラクタでのインスタンス生成() throws Exception { Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; ReflectConstructorExample ref = clazz.getDeclaredConstructor(String.class).newInstance("pro"); assertThat(ref, is(instanceOf(ReflectConstructorExample.class))); } @Test public void defaultコンストラクタでのインスタンス生成() throws Exception { Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; ReflectConstructorExample ref = clazz.getDeclaredConstructor(String.class, int.class).newInstance("def", 19); assertThat(ref, is(instanceOf(ReflectConstructorExample.class))); } @Test(expected = IllegalAccessException.class) public void privateコンストラクタでのインスタンス生成ができないこと() throws Exception { Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; ReflectConstructorExample ref = clazz.getDeclaredConstructor(int.class).newInstance(20); assertThat(ref, is(instanceOf(ReflectConstructorExample.class))); } }
テストコード
今回のテストコードの全体です。
ReflectConstructorExampleTest.java
package reflect; import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.junit.Assert.*; /** * Created by pppurple on 2016/07/26. */ @RunWith(Enclosed.class) public class ReflectConstructorExampleTest { public static class getConstructorの確認 { @Test public void getConstructorでpublicコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(); int mod = cons.getModifiers(); assertThat(mod, is(Modifier.PUBLIC)); } @Test(expected = NoSuchMethodException.class) public void getConstructorでprotectedコンストラクタが取得できないこと() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(String.class); } @Test(expected = NoSuchMethodException.class) public void getConstructorでdefaultコンストラクタが取得できないこと() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(String.class, String.class); } @Test(expected = NoSuchMethodException.class) public void getConstructorでprivateコンストラクタが取得できないこと() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(int.class); } } public static class getConstructorsの確認 { @Test public void getConstructorsでコンストラクタオブジェクトが取得できること() throws Exception { Class clazz = ReflectConstructorExample.class; Constructor[] cons = clazz.getConstructors(); Constructor[] expected = { clazz.getConstructor() }; assertThat(cons, is(arrayContainingInAnyOrder(expected))); } } public static class getDeclaredConstructorの確認 { @Test public void getDeclaredConstructorでpublicコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(); int mod = cons.getModifiers(); assertThat(mod, is(Modifier.PUBLIC)); } @Test public void getDeclaredConstructorでprotectedコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(String.class); int mod = cons.getModifiers(); assertThat(mod, is(Modifier.PROTECTED)); } @Test public void getDeclaredConstructorでdefaultコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(String.class, int.class); int mod = cons.getModifiers(); assertThat(mod, is(0)); } @Test public void getDeclaredConstructorでprivateコンストラクタが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getDeclaredConstructor(int.class); int mod = cons.getModifiers(); assertThat(mod, is(Modifier.PRIVATE)); } } public static class getDeclaredConstructorsの確認 { @Test public void getDeclaredConstructorsでコンストラクタオブジェクトが取得できること() throws Exception { Class clazz = ReflectConstructorExample.class; Constructor[] cons = clazz.getDeclaredConstructors(); Constructor[] expected = { clazz.getDeclaredConstructor(), clazz.getDeclaredConstructor(String.class), clazz.getDeclaredConstructor(String.class, int.class), clazz.getDeclaredConstructor(int.class) }; assertThat(cons, is(arrayContainingInAnyOrder(expected))); } } public static class Constructorクラスでコンストラクタ情報取得 { @Test public void getDeclaringClassでコンストラクタを宣言するクラスが取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(); Class clazz = cons.getDeclaringClass(); assertThat(clazz, is(equalTo(ReflectConstructorExample.class))); } @Test public void getNameでコンストラクタの名前が取得できること() throws Exception { Constructor cons = ReflectConstructorExample.class.getConstructor(); String name = cons.getName(); assertThat(name, is("reflect.ReflectConstructorExample")); } } public static class コンストラクタを利用したインスタンス生成確認 { @Test public void publicコンストラクタでのインスタンス生成() throws Exception { Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; ReflectConstructorExample ref = clazz.getConstructor().newInstance(); assertThat(ref, is(instanceOf(ReflectConstructorExample.class))); } @Test public void protectedコンストラクタでのインスタンス生成() throws Exception { Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; ReflectConstructorExample ref = clazz.getDeclaredConstructor(String.class).newInstance("pro"); assertThat(ref, is(instanceOf(ReflectConstructorExample.class))); } @Test public void defaultコンストラクタでのインスタンス生成() throws Exception { Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; ReflectConstructorExample ref = clazz.getDeclaredConstructor(String.class, int.class).newInstance("def", 19); assertThat(ref, is(instanceOf(ReflectConstructorExample.class))); } @Test(expected = IllegalAccessException.class) public void privateコンストラクタでのインスタンス生成ができないこと() throws Exception { Class<ReflectConstructorExample> clazz = ReflectConstructorExample.class; ReflectConstructorExample ref = clazz.getDeclaredConstructor(int.class).newInstance(20); assertThat(ref, is(instanceOf(ReflectConstructorExample.class))); } } }
ソースはあげておきました。
github.com
終わり。