什麼是反射?應用場景?

反射非常強大和有用,現在市面上絕大部分框架(spring、mybatis、rocketmq等等)中都有反射的影子,反射機制在框架設計中佔有舉足輕重的作用。

 

所以,在你Java進階的道路上,你需要掌握好反射。

 

怎麼才能學好反射,我們需要弄懂以下幾個問題:

1.反射是什麼?

2.反射有什麼用?

3.反射的實現原理?

4.怎麼用反射?

下面我就針對以上的疑問,一一來講解。

反射是什麼?

反射是java語言的一個特性,它允程序在運行時(注意不是編譯的時候)來進行自我檢查並且對內部的成員進行操作。

 

反射是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法,對於任意一個對象,都能夠調用它的任意方法和屬性,這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。

 

一句話總結:反射就是在運行時才知道要操作的類是什麼,並且可以在運行時獲取類的完整構造,並調用對應的方法。

 

爲什麼要用反射?

Java Reflection功能非常強大,並且非常有用,比如:

  • 獲取任意類的名稱、package信息、所有屬性、方法、註解、類型、類加載器等

  • 獲取任意對象的屬性,並且能改變對象的屬性

  • 調用任意對象的方法

  • 判斷任意一個對象所屬的類

  • 實例化任意一個類的對象

  • 通過反射我們可以實現動態裝配,降低代碼的耦合度,動態代理等。

 

怎麼使用反射?

一般情況下我們通過反射創建類對象主要有兩種方式:

  • 通過 Class 對象的 newInstance() 方法

  • 通過 Constructor 對象的 newInstance() 方法

 

第一種:通過 Class 對象的 newInstance() 方法。

Class clz = Class.forName("com.mikechen.reflection.JiaGou");JiaGou jg= (JiaGou)clz.newInstance();

第二種:通過 Constructor 對象的 newInstance() 方法

Class clz = Class.forName("com.mikechen.reflection.JiaGou");Constructor constructor = clz.getConstructor();JiaGou jg= (JiaGou)constructor.newInstance();

通過 Constructor 對象創建類對象可以選擇特定構造方法,而通過 Class 對象則只能使用默認的無參數構造方法,下面的代碼就調用了一個有參數的構造方法進行了類對象的初始化。

Class clz = Class.forName("com.mikechen.reflection.JiaGou");Constructor constructor = clz.getConstructor(String.class);JiaGou jg= (JiaGou)constructor.newInstance("mikechen的互聯網架構");

 

接下來我們就可以通過具體的API調用獲取到詳細的屬性或者方法等詳細了。

1、獲取類的成員變量的信息

 

//Field[] fields = cls.getDeclaredFields();

 

更加詳細成員變量獲取參考如下:

 

 

 

2、獲得類方法

 

//Method[] methods = cls.getDeclaredMethods();

更加詳細方法獲取參考如下:

 

 

3、獲得構造函數

 

// Constructor[] constructors = cls.getDeclaredConstructors();

 

更加詳細構造函數獲取參考如下:

 

這樣通過反射就可以做在運行時獲取類的完整構造,並獲得類信息了。

 

通過以上一個小案例瞭解了反射的使用,但如果你想對反射掌握得更好,還需深入理解反射背後的底層實現原理。

反射工作原理?

調用反射的總體流程如下:

1、當我們編寫完一個Java項目之後,每個java文件都會被編譯成一個.class文件。

 

 

2、這些class文件在程序運行時會被ClassLoader加載到JVM中,當一個類被加載以後,JVM就會在內存中自動產生一個Class對象。

 

 

3、通過Class對象獲取Field/Method/Construcor

 

我們一般平時是通過new的形式創建對象實際上就是通過這些Class來創建的,只不過這個class文件是編譯的時候就生成的,程序相當於寫死了給jvm去跑。

 

 

反射是什麼呢?當我們的程序在運行時,需要動態的加載一些類這些類可能之前用不到所以不用加載到jvm,而是在運行時根據需要才加載。

 

原來使用new的時候,需要明確的指定類名,這個時候屬於硬編碼實現,而在使用反射的時候,可以只傳入類名參數,就可以生成對象,降低了耦合性,使得程序更具靈活性。

反射的應用場景

舉個例子我們的項目底層數據庫有時是用mysql,有時用oracle,需要動態地根據實際情況加載驅動類,這個時候反射就有用了,假設 com.mikechen.java.myqlConnection,com.mikechen.java.oracleConnection這兩個類我們要用。

 

這時候我們在使用 JDBC 連接數據庫時使用 Class.forName()通過反射加載數據庫的驅動程序,如果是mysql則傳入mysql的驅動類,而如果是oracle則傳入的參數就變成另一個了。

 

Spring 框架的 IOC(動態加載管理 Bean),Spring通過配置文件配置各種各樣的bean,你需要用到哪些bean就配哪些,spring容器就會根據你的需求去動態加載,你的程序就能健壯地運行。

 

還有Spring AOP(動態代理)功能都和反射有關係。

 

除此之外還有很多框架:mybatis、dubbo、rocketmq等等都會用到反射機制。

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