Javaベース-Reflection:プライベートメソッド、メンバー変数へのアクセス


一.独自のプライベートメソッド、メンバー変数へのアクセス
1)例えばPrivateClassA.java
public class PrivateClassA {
	private Map<String, String> map = new HashMap<String, String>();
	
	public PrivateClassA(){		
		map.put("a", "a");
		map.put("b", "b");
	}	
	
	public void getPublic(){
		System.out.println("hi, I'm public method");
	}
	
	@SuppressWarnings("unused")
	private void getPrivate(){
		System.out.println("hi, I'm private method");
	}
}

2)アクセステストの例は以下の通りである.
public class PrivateClassATest {
	
	@Test
	public void testAccessPublic() throws Exception{
		Method med = PrivateClassA.class.getMethod("getPublic", new Class[]{});
		med.invoke(PrivateClassA.class.newInstance(), new Object[]{});
		
		Method med2 = PrivateClassA.class.getDeclaredMethod("getPublic", new Class[]{});
		med2.invoke(PrivateClassA.class.newInstance(), new Object[]{});
	}

	@Test
	public void testAccessPrivate() throws Exception{
		Method med = PrivateClassA.class.getDeclaredMethod("getPrivate", new Class[]{});
		
		med.setAccessible(true);
		med.invoke(PrivateClassA.class.newInstance(), new Object[]{});
	}
	
	// Access the private attribute
	@SuppressWarnings("unchecked")
	@Test
	public void testAccessPrivateAttribute()  throws Exception{
		//           ,   getDeclaredField
		Field f = PrivateClassA.class.getDeclaredField("map");
		f.setAccessible( true );
		Map<String, String> map = (Map<String, String>) f.get( new PrivateClassA() );
		
		Assert.assertEquals( map.size(), 2 );
		Iterator<String> keyIter = map.keySet().iterator();
		Assert.assertEquals( keyIter.next(), "a" );
		Assert.assertEquals( keyIter.next(), "b" );
		
	}

}

二.スーパークラスにアクセスするプライベートメソッド、メンバー変数  
1)たとえば、次のような子と親がいます.
// Super Class
public class PrivateFather {
	
	private void saidToChildren(){
		System.out.println("hi, child, I'm your private father");
	}
}

// Children
public class PrivateChildren extends PrivateFather{
	
}

2 ) プライベートメソッドにアクセスするツールクラスを作成する
public class ReflectionUtils {
	
	public static Method findMethod(Class srcClass, String name, Class[] parameters) throws NoSuchMethodException{
		Method method = null;
		try {
			method = srcClass.getDeclaredMethod(name, parameters);
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			if( srcClass.getSuperclass() == null ) 	throw e;
			else{
				return findMethod(srcClass.getSuperclass(), name, parameters);
			}
		}
		return method;
	}
}

 3 ) Junit Test cases
public class FatherPrivateMethodTest{
	
	@Test
	public void testGetPrivateFromFather() throws IllegalArgumentException, 
IllegalAccessException, InvocationTargetException, InstantiationException{
		Method superPrivateMed = null;
		try {
			superPrivateMed = ReflectionUtils.findMethod(PrivateChildren.class, "saidToChildren", null);
			superPrivateMed.setAccessible(true);
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		superPrivateMed.invoke(PrivateChildren.class.newInstance(), null);
		superPrivateMed.invoke(new PrivateChildren(), null);
	}
}