反射

這篇文章說一些關於反射的東西

先來了解一下關於java中類加載機制的東西

類加載器

什麼是類的加載

當程序要使用某個類時,如果該類還未被加載到內存中,則系統會通過加載,連接,

初始化三步來實現對這個類進行初始化。

一個類在加載過程中的三部曲:

1.加載 

就是指將class文件讀入內存,併爲之創建一個Class對象. 

任何類被使用時系統都會建立一個Class對象

2.連接

驗證 是否有正確的內部結構,並和其他類協調一致

準備 負責爲類的靜態成員分配內存,並設置默認初始化值

解析 將類的二進制數據中的符號引用替換爲直接引用

3.初始化 就是我們以前講過的初始化步驟

(2)類的加載時機(掌握)

 創建類的實例

 訪問類的靜態變量,或者爲靜態變量賦值

 調用類的靜態方法

 使用反射方式來強制創建某個類或接口對應的java.lang.Class對象

 初始化某個類的子類

 直接使用java.exe命令來運行某個主類

(3)加載器分類

 類加載起的作用?

負責將.class文件加載到內在中,併爲之生成對應的Class對象。

類加載器的分類

Bootstrap ClassLoader 根類加載器

也被稱爲引導類加載器,負責Java核心類的加載

比如System,String等。在JDK中JRE的lib目錄下rt.jar文件中

Extension ClassLoader 擴展類加載器

負責JRE的擴展目錄中jar包的加載。

在JDK中JRE的lib目錄下ext目錄

wKiom1kljPLjVZhBAACIcP8-0X4786.png-wh_50


Student.java--Student.class(字節碼文件)--看成一個對象,這個對象就叫字節碼文件對象--對應的類Class

什麼是反射?(畫圖描述)

反射就是通過字節碼文件對象去使用成員。

(1)獲取字節碼文件對象的三種方式:

Object類的getClass()方法

數據類型的靜態class屬性

Class類的靜態方法forName()

public static void main(String[] args) throws ClassNotFoundException {
//獲取Person類對應的Class字節碼文件對象
//A:Object類的getClass()方法
Person p1 = new Person();
Person p2 = new Person();
Class c1 = p1.getClass();
Class c2 = p2.getClass();
System.out.println(p1==p2);//false
System.out.println(c1==c2);//true
//每一個類會對應一個字節碼文件對象,而這個字節碼文件對象就是這個類的原型,每一個類有且僅有一個字節碼文件對象
System.out.println("-------------");
//B:數據類型的靜態class屬性
Class c3 = Person.class;
System.out.println(c2==c3);
System.out.println("---------------");
//C:Class類的靜態方法forName()
//public static Class<?> forName(String className),在這裏所說的類名是全類名(帶包名的類名)
//Class c4 = Class.forName("Person");//java.lang.ClassNotFoundException: Person
Class c4 = Class.forName("com.edu_01.Person");
System.out.println(c3==c4);


 使用反射的方式創建對象,調用方法。

創建某一個類對應的字節碼文件對象  -- 全類名(className=com.edu_01.Person)

將對象需要調用的方法,依然利用反射的方式獲取該方法的對應的對象 -- 方法名(classMethod=study)

舉例:第十七次代碼com.edu_06。


通過反射來獲取成員變量:

public static void main(String[] args) throws Exception {
    //獲取Perosn類對應的字節碼文件對象
    Class c = Class.forName("com.edu_01.Person");
    //利用反射獲取一個[Perosn對象
    Constructor con = c.getConstructor();
   bject obj = con.newInstance();
    //獲取所有公共的字段對象
    //public Field[] getFields()獲取公有的成員變量
    Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field);
}
//public Field[] getDeclaredFields()獲取全部的成員變量,包括私有
Field[] fields2 = c.getDeclaredFields();
for (Field field : fields2) {
System.out.println(field);
}
//public Field getDeclaredField(String name) 傳入變量名稱返回指定的成員變量對象,包括私有
//獲取String name;字段
Field f = c.getDeclaredField("name");
//public void set(Object obj, Object value)
/**
 * 參數1:需要設置的對象
 * 參數2:需要給這個對象設置什麼值
 */
//取消訪問修飾符的限制
f.setAccessible(true);
f.set(obj, "謝娜");
//public Field getField(String name)傳入變量名稱返回指定的成員變量對象,僅可獲取公有的
//獲取public int age;
Field f2 = c.getField("age");
f2.set(obj, 30);
Field f3 = c.getDeclaredField("address");
//取消權限檢測
f3.setAccessible(true);
f3.set(obj, "湖南");
System.out.println(obj);









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章