1. 程式人生 > >反射的原理和實現

反射的原理和實現

反射:

反射應用在一些通用性比較高的程式碼中。

        一般的框架,大多數都是使用反射來實現的。

        在框架開發中,都是基於配置檔案開發。

        在配置檔案紅配置了類,可以通過反射得到類中的所有內容,可以讓類中某個方法執行。

        類中所有的內容:屬性、沒有引數的構造方法、有引數的構造方法、普通方法。   

分析反射的原理:

首先把需要java檔案儲存到本地硬碟  .java檔案

編譯java檔案成  .class檔案

使用jvm,把class檔案通過類載入載入到記憶體中

萬事萬物都是物件,class檔案在記憶體中使用class類表示

 當使用反射的時候,首先需要獲取到class

類,得到這個類之後,就可以得到class檔案裡的所有內容。

        -包含屬性,構造方法,普通方法

屬性通過一個類 Filed

構造方法通過一個類 Construction

        普通方法通過一個類 Method

使用反射操作類裡面的無引數的構造方法:

        首先獲取到Class

       //獲取Class類的三種方式
       Class class1 = testDemoperson.class;
       Class class2 = new testDemoperson().getClass();
       Class class3 = Class.forName("test04.testDemoperson");

    比如:要對一個類進行例項化,可以new,不使用new,怎麼獲取?

    //得到Class
    Class c3 = Class.forName("test04.testDemoperson");
    //得到testDemoperson類例項
    testDemoperson p = (testDemoperson) c3.newInstance();

使用反射操作有引數的構造方法:

publicstaticvoid test2() throws Exception{

        //得到Class

        Class c1 = Class.forName("test04.testDemoperson");

        //使用有引數的構造方法

        //c1.getConstructor();//獲取所有的構造方法。

        //傳遞有引數的構造方法裡面的引數型別,型別使用class形式傳遞

        Constructor cs = c1.getConstructor(String.class,String.class);

        //通過有引數的構造方法設定值

        //通過有引數的構造方法建立person例項

        testDemoperson p8 = (testDemoperson) cs.newInstance("lisi","200");

        System.out.println(p8.getId()+" "+p8.getName());

    }

使用反射來操作屬性:

publicstaticvoid test3() throws Exception {

        //得到Class類

        Class c9 = Class.forName("test04.testDemoperson");

        //得到name屬性

        //得到testDemoperson的例項

        testDemoperson p11 = (testDemoperson) c9.newInstance();

        //通過這個方法得到屬性,引數是屬性的名稱

        Field f = c9.getDeclaredField("name");

        //操作的是私有的屬性,不讓操作,設定可以操作私有屬性setAccessible(true);

        f.setAccessible(true);

        //設定name值 set方法,兩個引數:第一個是引數的例項,第二個是設定的值。

        f.set(p11, "王5");//相當於在 p.name = "王5";

        System.out.println(f.get(p11));//相當於p.name

    }

使用反射操作普通方法:

使用Method類表示普通方法

publicstaticvoid test6() throws Exception{

        //得到Class類

        Class c5 = Class.forName("test04.testDemoperson");

        //得到testDemoperson例項

        testDemoperson p7 = (testDemoperson) c5.newInstance();

        //得到普通的方法

        //c5.getDeclaredMethods();//得到所有的普通方法

        //傳遞兩個引數:第一個引數是方法名稱,第二個引數是通過方法設定的值

        Method m4 = c5.getDeclaredMethod("setName", String.class);

        //讓setName方法執行,執行設定值

        //使用invoke(p4,"張");

        //傳遞兩個引數,第一個是testDemoperson的例項,第二個引數是設定的值

//執行了invoke方法之後,相當於執行了setName方法,同時通過這個方法設定了一個值叫“張”

        m4.invoke(p7, "張");

        System.out.println(p7.getName());

    }

注意:

        操作私有的方法,需要設定值是true

        m4.setAccessible(true);

  當操作的方法是靜態的方法的時候,因為靜態方法呼叫方式是類名.方法名,

        不需要類的例項。使用反射操作靜態方法的時候也是不需要例項的。

        在invokie方法的第一個引數裡面,寫一個null

            m4.invoke(null,“張”);