S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

インナークラスのインスタンス生成

Class.forNameでClassクラスのインスタンスを取得して、newInstanceするとInstaniationExceptionになる。
なので、リフレクションのConstructorから、インナークラスを持ったクラスのインスタンスを第1引数とするコンストラクタを取得して、newInstanceする。
(必要であれば第2引数以降を適用する)

package pkg;
import java.lang.reflect.Constructor;
// インナークラスを持ったクラス
public class InnerClassTest {
  public InnerClassTest() {
    super();
  }
  public static void main(String[] args) throws Exception {
    ((InnerClassTest) Class.forName("pkg.InnerClassTest").newInstance()).extecute();
  }
  // 実行
  private void extecute() throws Exception {
    createInstance("pkg.InnerClassTest$InnerClass").print();
    createInstance("pkg.InnerClassTest$InnerClassEx").print();
    // これはInstaniationException
    //((Print) Class.forName("pkg.InnerClassTest$InnerClass").newInstance()).print();
  }
  // Printインターフェースを実装したインナークラスを生成する
  private Print createInstance(String name) throws Exception {
    Class<Print> c = (Class<Print>) Class.forName(name);
    // インナークラスを持ったクラスのインスタンス(this)がコンストラクタの第1引数
    return (Print) c.getDeclaredConstructor(this.getClass()).newInstance(this); 
  }
  // インナークラスのインターフェース
  public interface Print {
    public void print();
  }
  // インナークラス
  public class InnerClass implements Print {
    public InnerClass() {
      super();
    }
    public void print() {
      System.out.println(this.getClass().getName());
    }
  }
  // 継承したインナークラス
  public class InnerClassEx extends InnerClass {
    public InnerClassEx() {
      super();
    }    
  }
}

■参考
Javaリフレクションメモ(Hishidama's Java Reflection Memo)#内部クラスのインスタンス生成
サブクラスで.newInstance()でインスタンス化できない | JavaのQ&A【OKWave】