1. 程式人生 > >通過反射建立私有化類的物件,呼叫類的私有方法,改變私有屬性

通過反射建立私有化類的物件,呼叫類的私有方法,改變私有屬性

首先建立一個類

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”

輸出結果:

這裡寫圖片描述