通過反射建立私有化類的物件,呼叫類的私有方法,改變私有屬性
阿新 • • 發佈:2018-11-25
首先建立一個類
public class ReflectDemo {
private int m=0; //私有屬性
private ReflectDemo(){ //私有無參建構函式
}
public ReflectDemo(int aa){
//有參建構函式
}
private int add(int a,int b){ //私有方法
return a+b;
}
public int getM(){
return m;
}
}
在這裡要先說一下建構函式:
建構函式分為公有的和私有的,定義成private,在類的外面,就不能生成類的物件了
如果一個類沒有提供任何的建構函式,會自動生成一個無參的建構函式,這個建構函式是public。
然後我們要了解三個反射包中的類:
Constructor:代表類的單個構造方法,通過Constructor我們可以執行一個類的某個構造方法(有參或無參)來建立物件。
Method:代表類中的單個方法,可以用於執行類的某個普通方法,有參或無參,並可以接收返回值。
Field:代表類的單個屬性,用於set或get該屬性。
setAccessible: setAccessible()方法來抑制Java訪問許可權的檢查的。
AccessibleObject:以上三個類的父類,提供了對構造方法、普通方法、和屬性的訪問控制的能力。
public class ReflectTest {
public static void main(String[] args) throws Exception {
/**
* 建立私有化類的物件
*/
//1.獲取類的無參構造方法
Constructor<ReflectDemo> constructor=ReflectDemo.class.getDeclaredConstructor();
//2.設定取消訪問檢查,是訪問私有構造方法的關鍵
constructor.setAccessible(true );
//3.呼叫該構造方法,獲得物件
ReflectDemo reflectDemo=constructor.newInstance();
/**
* 使用反射呼叫私有方法
*/
//1.根據方法名和方法引數獲取方法物件
//第一個引數是具體呼叫該方法的物件
//後面引數是執行該方法的具體引數
Method method=ReflectDemo.class.getDeclaredMethod("add",int.class,int.class);
//Method method=ReflectDemo.class.getDeclaredMethod("add",new Class[]{int.class,int.class}); 另一種方法
//2.取消訪問檢查,是訪問私有方法的關鍵
method.setAccessible(true);
//3.呼叫私有方法並獲得返回值
int i=(Integer) method.invoke(reflectDemo, 1,2);
System.out.println(i);
/**
* 使用反射改變私有屬性
*/
Field field=ReflectDemo.class.getDeclaredField("m");
field.setAccessible(true);
field.setInt(reflectDemo, 2);
System.out.println(reflectDemo.getM());
/**
* 通過new物件,這裡因為ReflectDemo設定了私有的無參建構函式所以不能例項化無參的物件。
*/
ReflectDemo ddd=new ReflectDemo(22);
//這裡的物件ddd與上面的reflectDemo是不同的物件,所以上面通過反射設定的私有屬性並不會影響這裡的物件
System.out.println(ddd.getM());
}
}
method中的invoke方法:
函式原型:Object Java.lang.reflect.Method.invoke(Object receiver, Object… args)
//Method類的invoke(Object obj,Object args[])方法接收的引數必須為物件,
//如果引數為基本型別資料,必須轉換為相應的包裝型別的物件。invoke()方法的返回值總是物件,
//如果實際被呼叫的方法的返回型別是基本型別資料,那麼invoke()方法會把它轉換為相應的包裝型別的物件,再將其返回
receiver:該方法所在類的一個物件
args: 傳入的引數 如 100,“hello”
輸出結果: