反射 is 框架的靈魂

背景:
我不相信你會問—啥是框架? (簡單理解爲可複用的代碼)像現在很流行的框架如 Spring , Spring boot,Spring AOC 等都是框架,組成它們的代碼中總會見到反射機制。

簡介:
反射: 將類的組成部分封裝成一個對象。
用一張圖解釋哈:
在這裏插入圖片描述
過程解釋:
還是一個老生常談的問題,我們用高級語言編寫的代碼如何被計算機執行? 都知道計算機只能執行機器碼。 所以我們編譯高級語言代碼最終也會生成機器碼,只不過中間有一個過度的部分那就是字節碼。利用 javac 生成字節碼後,我們想執行這個程序。又知道計算機是從內存中讀取指令和數據的,我們利用反射將字節碼文件加載進內存,然後被計算機所執行。

使用反射的好處:
1 可以在程序運行中操縱這些對象
2 可以解耦,提高程序的可擴展性

===============================================================

應用舉例:

獲取 Class 對象的方式(可以理解 Class 對象是反射的另一種體現):

1 Class.forName("全類名")    // 將磁盤中的對應代碼加載進內存,返回 Class 對象(**多用於配製文件)

2 類名.class    //通過類名的屬性獲取對象(內存中),(**多用於參數傳遞)

3 對象.getclass() // getclass()在Object對象中定義着(**多用於對象獲取字節碼的方式)

//結論

同一個字節碼文件(*.class)在一次程序運行中只會被加載一次進內存,不論通過那種方式獲取 Class 都是代指同一個對象

Class 對象的功能:


  // 獲取內存中的成員變量們
  - cls.getFileds();   // 獲取 public 修飾的成員變量
  - cls.getFiled(String name);  // 獲取指定 public 修飾的成員變量
  - cls.getDeclaredFileds(); // 獲取全部成員變量(忽略修飾符)
  - cls.getDeclaredFiled(String name); // 獲取指定成員變量(忽略修飾符)
 注:獲取 private 修飾的變量後想給其賦值必須先執行能忽略修飾符的代碼--> 
 - cls.setAccessible(True);

 //  獲取內存中的構造方法們
   - cls.getConstructor(String.class,int.class);  // 獲取指定 public 修飾的構造方法
  - cls.getConstructors(); // 獲取 public 修飾的構造方法
   - cls.getDeclaredConstructor(String.class,int.class);// 獲取指定 public 修飾的構造方法(忽略修飾符)
  - cls.getDeclaredConstructors();  // // 獲取構造方法(忽略修飾符)
  

獲取構造方法有啥用呢??? 哈哈,當然是創建對象啦。

   Constructor c =   cls.getConstructor(String.class,int.class);
	Object o =  c.newInstance("ss",70);
	
 // 獲取成員方法也是相似的代碼(這裏就忽略了)

我想看到這裏你還是對反射的作用記憶不深刻,也不知道用它來獲取對象和獲取對應的方法並執行有啥用? 如果你有這個疑問,那麼問題就來了:

問: 利用反射機制,寫一個框架,可以創建任意對象,執行任意方法。

是不是沒有思路??? 是不是覺得雖然知道反射但還是不會用它解決問題?如果你一上來就寫代碼,根據傳入指定的全類名和方法名這種辦法,可行是可行但耦合度太高了。
簡單的處理是 配製文件+反射(在配置文件內寫全類名,和指定要執行的方法名。)

/**
     - 創建配置文件(後綴名一定爲 .properties)
     - 創建配置文件對象
     - 獲取配置文件
     - 根據配置文件對象獲取配置文件內容
     - 根據內容創建對象
      - 根據內容找到方法並執行
 **/
 Properties pro = new Properties();
 //獲取配置文件
 InputStream in = getclass.getClassLoad().getResourceAsStream("配置文件路徑")
 //加載配置文件
 pro.load(in);
//獲取配置文件內的內容
String className = pro.getProperty("className");
String method_name = pro.getProperty("method_name");
//利用反射創建對象,執行對應方法
Class cls = class.forNmae("className");  // 加載對象進內存
Object obj = cls.newInstance(); //創建對象
Method me = cls.getMethod("method_name"); //獲取指定方法
me.invoke(obj); //執行指定方法(需要對象爲形參)

總結:
上面寫到了一些反射的常見用法,以及在框架中如何使用反射機制,極大的簡化了代碼量。我希望對你有所幫助。

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