Java反射メカニズムアクセスクラスプライベートメソッドと変数
8279 ワード
Java反射メカニズムアクセスクラスプライベートメソッドと変数
背景
Javaの反射メカニズムを利用して、実行時のクラス情報(RTTI)を得ることができ、従来のRTTIとは異なり、反射は実行時に.classファイルを得ることができ、.classファイルを開いてチェックすることができ、すべてのJavaの反射は強い柔軟性を持っている.反射は、使用可能なメソッドをチェックし、メソッド名を返すメカニズムを提供します.もちろん、ドメイン変数メンバーなどの他の情報を得ることもできます.反射機構により変数を得るためのプライベートメソッドと変数は理論的に実行可能であり,手順は非常に簡単であり,Javaコードと組み合わせて紹介する.
1.クラス構造
2.このクラスのプライベート変数とメソッドへのアクセス
まずClass.getMethod(String name,Class...parameterType)はこのクラスおよび親クラスがアクセスできる方法を得ることができ,ここでの方法はpublic void h()であるため,直接反射によって得ることができる.Class.getDeclaredField(String name)を使用すると、プライベートメソッド(親を取得できない)を含むクラスのすべてのメソッドを取得できます.これにより、プライベートメソッドを反射的に呼び出すことができます.invoke(...)を呼び出す前にsetAccessible(boolean flag)を追加する必要があります.そうしないとjava.lang.IllegalAccessExceptionが生成されます.この方法はAccessibleObjectクラスから継承されます.Method.setAccessible(true)を呼び出すと、アクセス制御はこのMethodオブジェクトにのみ機能し、他のMethodオブジェクトには機能しません.
同様に、Class.getDeclaredFiled(String name)は、nameに基づいてクラスのプライベートドメインオブジェクトを取得してアクセスすることもできますが、スーパークラスのドメインオブジェクトは取得できません.
3.親プライベート変数とメソッドへのアクセス
Class.getSuperclass()を使用すると、クラス、インタフェース、またはvoidを含むエンティティのスーパークラスが得られます.スーパークラスが得られると、以前の方法で反射してスーパークラスのプライベートメソッドとプライベートドメインオブジェクトにアクセスできます.
4.いくつかの反射機構の応用例は、オブジェクトが属するクラスおよびスーパークラスのすべてのドメイン変数名(プライベートを含む) を得る. final Stringが指す文字列の内容を変更する
5.反射メカニズムによるプライベートドメインへのアクセスを防止する方法はありますか?
背景
Javaの反射メカニズムを利用して、実行時のクラス情報(RTTI)を得ることができ、従来のRTTIとは異なり、反射は実行時に.classファイルを得ることができ、.classファイルを開いてチェックすることができ、すべてのJavaの反射は強い柔軟性を持っている.反射は、使用可能なメソッドをチェックし、メソッド名を返すメカニズムを提供します.もちろん、ドメイン変数メンバーなどの他の情報を得ることもできます.反射機構により変数を得るためのプライベートメソッドと変数は理論的に実行可能であり,手順は非常に簡単であり,Javaコードと組み合わせて紹介する.
1.クラス構造
class Food{
private String foodname;
Food(String foodname){
this.foodname = foodname;
}
private void f(){
System.out.println("private Food Method");
}
}
class Cake extends Food{
private String privateCakeName;
public String publicCakeName;
Cake(String priName, String pubName, String superName){
super(superName);
privateCakeName = priName;
publicCakeName = pubName;
}
private void g(){
System.out.println("private Cake Method");
}
public void h(){
System.out.println("public Cake Method");
}
}
2.このクラスのプライベート変数とメソッドへのアクセス
まずClass.getMethod(String name,Class...parameterType)はこのクラスおよび親クラスがアクセスできる方法を得ることができ,ここでの方法はpublic void h()であるため,直接反射によって得ることができる.Class.getDeclaredField(String name)を使用すると、プライベートメソッド(親を取得できない)を含むクラスのすべてのメソッドを取得できます.これにより、プライベートメソッドを反射的に呼び出すことができます.invoke(...)を呼び出す前にsetAccessible(boolean flag)を追加する必要があります.そうしないとjava.lang.IllegalAccessExceptionが生成されます.この方法はAccessibleObjectクラスから継承されます.Method.setAccessible(true)を呼び出すと、アクセス制御はこのMethodオブジェクトにのみ機能し、他のMethodオブジェクトには機能しません.
JDK API
AccessibleObject Field、Method Constructor 。 Java 。 、 ( ) 、 , Field、Method Constructor 、 , , 。
accessible ( Java Object Serialization ) 。
setAccessible
public void setAccessible(boolean flag)
throws SecurityException
accessible 。 true Java 。 false Java 。
setAccessible , true false , , , , , , , , AccessibleObject setAccessible() , Field,Method Constructor AccessibleObject, , setAccessible() , 。 , , java.security.manager setAccessible() 。 , API , URLClassLoader 。
同様に、Class.getDeclaredFiled(String name)は、nameに基づいてクラスのプライベートドメインオブジェクトを取得してアクセスすることもできますが、スーパークラスのドメインオブジェクトは取得できません.
Cake applecake = new Cake("smallAppleCake", "bigAppleCake", "cake");
try {
//
Cake.class.getMethod("h").invoke(applecake);
//Output:public Cake Method
//
Method privateMethod = Cake.class.getDeclaredMethod("g");
privateMethod.setAccessible(true);
privateMethod.invoke(applecake);
//Output:private Cake Method
//
Field privateField = Cake.class.getDeclaredField("privateCakeName");
privateField.setAccessible(true);
System.out.println(privateField.get(applecake));
//Output:smallAppleCake
} catch (Exception e) {
e.printStackTrace();
}
3.親プライベート変数とメソッドへのアクセス
Class.getSuperclass()を使用すると、クラス、インタフェース、またはvoidを含むエンティティのスーパークラスが得られます.スーパークラスが得られると、以前の方法で反射してスーパークラスのプライベートメソッドとプライベートドメインオブジェクトにアクセスできます.
Cake applecake = new Cake("smallAppleCake", "bigAppleCake", "cake");
try {
//
Method privateMethod = Cake.class.getSuperclass().getDeclaredMethod("f");
privateMethod.setAccessible(true);
privateMethod.invoke(applecake);
//Output:private Food Method
//
Field privateField = Cake.class.getSuperclass().getDeclaredField("foodname");
privateField.setAccessible(true);
System.out.println(privateField.get(applecake));
//Output:cake
} catch (Exception e) {
e.printStackTrace();
}
4.いくつかの反射機構の応用例
private List getInheritedPrivateFields(Class> type) {
List result = new ArrayList();
Class> i = type;
while (i != null && i != Object.class) {
Collections.addAll(result, i.getDeclaredFields());
i = i.getSuperclass();
}
return result;
}
final String s = "abc";
System.out.println(s);
//Output:abc
Field field = s.getClass().getDeclaredField("value");
field.setAccessible(true);
char[] chars = (char[])field.get(s);
chars[0] = '1';
chars[1] = '2';
chars[2] = '3';
System.out.println(s);
//Output:123
5.反射メカニズムによるプライベートドメインへのアクセスを防止する方法はありますか?
SecurityManager
は、setAccessible
の呼び出しを制限することができ、それ以外に方法はない.