読者です 読者をやめる 読者になる 読者になる
スポンサーリンク

Javaで,private変数・privateメソッド・privateコンストラクタを,外部から呼び出そう (リフレクションの方法)

java hack プログラミング

Javaでは,クラス内でprivate宣言されたメンバは,普通は外部からは呼び出せない。

しかし,リフレクションを使えば,それも可能。


本エントリでは,以下のサンプルコードを示す。

(1)

  • privateなインスタンス変数の呼び出し方法
  • privateなクラス変数の呼び出し方法
  • privateなインスタンスメソッドの呼び出し方法
  • privateなクラスメソッドの呼び出し方法

(2)

  • privateなコンストラクタの呼び出し方法

(1)private変数やprivateメソッドへのアクセス

Hoge.java

import java.lang.reflect.Method;
import java.lang.reflect.Field;


public class Hoge
{
	public static void main( String[] argv ) throws Exception
	{
		// Fugaの「クラス情報」が収められたオブジェクト
		Class<Fuga> c = Fuga.class;
		
		// Fugaのインスタンス
		Fuga fuga = new Fuga();
		
		
		// 以下で,privateメンバにアクセスする。
		
		
		// privateメソッド(引数なし)を呼び出して実行
		Method m1 = c.getDeclaredMethod( "boo1" );
		m1.setAccessible( true );
		m1.invoke( fuga );
		
		// privateメソッド(引数あり)を呼び出して実行
		Method m2 = c.getDeclaredMethod( "boo2", String.class );
		m2.setAccessible( true );
		m2.invoke( fuga, "World" );
		
		// privateなstaticメソッドを呼び出して実行
		Method m2 = c.getDeclaredMethod( "boo3" );
		m2.setAccessible( true );
		m2.invoke( null ); // staticなのでインスタンスを渡す必要が無い
		
		// privateな変数を読み取り
		Field f1 = c.getDeclaredField( "boo_instance" );
		f1.setAccessible( true );
		int m = (Integer) f1.get( fuga );
		System.out.println( "m = " + m );
		
		// privateなstatic変数を読み取り
		Field f2 = c.getDeclaredField( "boo_static" );
		f2.setAccessible( true );
		int n = (Integer) f2.get( null ); // staticなのでインスタンスを渡す必要が無い
		System.out.println( "n = " + n );
	}
}


// privateメンバを持つクラス
class Fuga
{
	// privateなstatic変数
	private static int boo_static = 1;
	
	// privateなインスタンス変数
	private int boo_instance;
	
	// 引数の無いprivateメソッド
	private void boo1()
	{
		System.out.println( "This is a private method." );
	}
	
	// 引数のあるprivateメソッド
	private void boo2( String s )
	{
		System.out.println( "Hello, " + s + "!" );
	}
	
	// private なstaticメソッド
	private static void  boo3()
	{
		System.out.println( "This is a private static method." );
	}
	
	
	public Fuga()
	{
		// インスタンスが生成されたら,
		// インスタンス変数に値をセット
		this.boo_instance = 1;
	}
}


コンパイルして実行

 >javac Hoge.java
 
 >java Hoge
 
 This is a private method.
 Hello, World!
 This is a private static method.
 m = 1
 n = 1


privateメソッドの呼出し手順:

  1. 該当クラスのClassオブジェクトを生成
  2. ClassからMethodオブジェクトを生成
  3. Methodのアクセス権限を変更
  4. invokeで実行
    1. インスタンスメソッドの場合は,インスタンスを渡す。
    2. クラスメソッドの場合は,nullを渡す。


private変数(フィールド)の呼出し手順:

  1. 該当クラスのClassオブジェクトを生成
  2. ClassからFieldオブジェクトを生成
  3. Fieldのアクセス権限を変更
  4. getで取得
    1. インスタンス変数の場合は,インスタンスを渡す。
    2. クラス変数の場合は,nullを渡す。

Javaリフレクションメモ:privateメンバへのアクセス
http://www.ne.jp/asahi/hishidama/home...

Javaでprivateなインスタンス変数にアクセスする方法
http://aheadonestep.blogspot.com/2008...

Dynamically invoking a static method without instance reference
http://www.javaworld.com/javaworld/ja...

  • 静的メンバをinvokeする場合は,invokeの引数は無視される。とりあえずnullを渡せばよい。

(2)privateなコンストラクタへのアクセス

Hoge.java

import java.lang.reflect.Constructor;


public class Hoge
{
	public static void main( String[] argv ) throws Exception
	{
		// Fugaの「クラス情報」が収められたオブジェクト
		Class<Fuga> c = Fuga.class;
		
		
		// 以下で,Fugaのインスタンスを作成する。
		
		
		// privateなコンストラクタを呼び出して実行
		Constructor<Fuga> con = c.getDeclaredConstructor();
		con.setAccessible( true );
		Fuga fuga = con.newInstance();
		fuga.blah(); // インスタンスメソッドを実行
	}
}


// コンストラクタがprivateなのでインスタンスを作れないクラス
class Fuga
{
	private Fuga(){}
	
	// インスタンスメソッド
	public void blah()
	{
		System.out.println( "This is an instance of Fuga." );
	}
}


コンパイルして実行

 >javac Hoge.java
 
 >java Hoge
 This is an instance of Fuga.

privateなコンストラクターしか持たないクラスの生成
http://oshiete.goo.ne.jp/qa/5897242.html