ksino's diary

覚えたことを忘れないように、小さなことでも書いていく。

privateなインナークラスをリフレクションで触る

privateなインナークラスをリフレクションで触る方法について調べました。
Constructorクラスを取得する際の引数列がポイントかな。。

対象のクラス
public class OuterClass {
    
    public String outer(String str) {
        InnerClass inner = new InnerClass(str);
        return inner.inner();
    }

    private class InnerClass { 
        private String str;

        public InnerClass(String str) {
            super();
            this.str = str;
        }
        
        public String inner() {
            return str;
        }
    }
}
実行クラス
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import org.junit.Assert;
import org.junit.Test;

public class OuterClassTest {

    @Test
    public void test() throws Exception {
        
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        Class innerClazz = loader.loadClass("jp.gr.java_conf.ksino.test.OuterClass$InnerClass");
        
        // 第1引数に外側クラスのClassオブジェクトを指定する
        Class[] constructorParameterTypes = new Class[]{OuterClass.class, String.class};
        Constructor constructor = innerClazz.getDeclaredConstructor(constructorParameterTypes);
        constructor.setAccessible(true);
        
        String str = "じぇじぇじぇ";
        Object target = constructor.newInstance(new OuterClass(), str);

        Class[] methodParametertypes = new Class[]{};
        Method method = innerClazz.getDeclaredMethod("inner", methodParametertypes);
        String[] methodParameters = new String[]{};
        
        String ret = (String)method.invoke(target, methodParameters);
        
        Assert.assertEquals(str, ret);
    }
}