技術メモ

技術メモ

ラフなメモ

Javaのリフレクションを使ってインスタンス生成を試す

リフレクションの勉強をします。リフレクションといってもカバーする領域が広い(応用範囲が広い)ので、今回はインスタンスの生成に関するリフレクションについて勉強します。

Classオブジェクトを取得

  • クラスリテラルを使用する
  • オブジェクトに対して、getClassメソッドを使う
  • staticメソッドのClass.forNameを使用して、完全修飾名により検索する
  • クラスローダから取得する

クラスリテラルを使用する

Foo.java

テスト用クラスとして以下を準備します。

public class Foo {
    private String bar;
    private Integer hoge;
    private Double fuga;

    static {
        System.out.println("static block.");
    }

    public Foo() {
        System.out.println("constructor.");
    }

    protected Foo(String bar) {
        this.bar = bar;
    }

    Foo(Integer hoge) {
        this.hoge = hoge;
    }

    private Foo(Double fuga) {
        this.fuga = fuga;
    }

    public String getBar() {
        return this.bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

    public int publicMethod() {
        return 1;
    }

    protected int protectedMethod() {
        return 2;
    }

    int defaultMethod() {
        return 3;
    }

    private int privateMethod() {
        return 4;
    }

    public static int staticMethod() {
        return 11;
    }

    @Override
    public String toString() {
        return "Foo [bar=" + bar + "]";
    }
}

Class<? extends Foo> clazz1 = Foo.class;

オブジェクトに対して、getClassメソッドを使う

Foo foo = new Foo();
Class<? extends Foo> clazz2 = foo.getClass();

staticメソッドのClass.forNameを使用して、完全修飾名により検索する

Class<Foo> clazz3;
try {
    clazz3 = (Class<Foo>) Class.forName("jp.co.sample.Foo");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

クラスローダから取得する

ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class<?> clazz4;
try {
    clazz4 = loader.loadClass("jp.co.sample.Foo");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Classオブジェクトからインスタンス生成

リフレクションでインスタンスを生成するには、Constructorオブジェクトを取得し、Constructor#newInstance()を使います。

確認用テストコード

    @Test
    public void クラスオブジェクトからインスタンス生成1() throws Exception {
        Class<Foo> clazz = Foo.class;
        Foo foo = clazz.getConstructor().newInstance();
        assertThat(foo, is(instanceOf(Foo.class)));
    }

    @Test
    public void クラスオブジェクトからインスタンス生成2() throws Exception {
        Foo object = new Foo();
        Class<? extends Foo> clazz = object.getClass();
        Foo foo = clazz.getConstructor().newInstance();
        assertThat(foo, is(instanceOf(Foo.class)));
    }

    @SuppressWarnings("unchecked")
    @Test
    public void クラスオブジェクトからインスタンス生成3() throws Exception {
        Class<Foo> clazz = null;
        try {
            clazz = (Class<Foo>) Class.forName("jp.co.sample.Foo");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Foo foo = clazz.getConstructor().newInstance();
        assertThat(foo, is(instanceOf(Foo.class)));
    }

    @SuppressWarnings("unchecked")
    @Test
    public void クラスオブジェクトからインスタンス生成4() throws Exception {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class<Foo> clazz = null;
        try {
            clazz = (Class<Foo>) loader.loadClass("jp.co.sample.Foo");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Foo foo = clazz.getConstructor().newInstance();
        assertThat(foo, is(instanceOf(Foo.class)));
    }