天天看點

Java反射機制是什麼?

Java反射機制是Java語言的一個重要特性。在學習Java反射機制前,大家應該先了解兩個概念,編譯期和運作期。

編譯期是指把源碼交給編譯器編譯成計算機可以執行的檔案的過程。在 Java 中也就是把 Java 代碼編成 class 檔案的過程。編譯期隻是做了一些翻譯功能,并沒有把代碼放在記憶體中運作起來,而隻是把代碼當成文本進行操作,比如檢查錯誤。

運作期是把編譯後的檔案交給計算機執行,直到程式運作結束。所謂運作期就把在磁盤中的代碼放到記憶體中執行起來。

Java 反射機制是在運作狀态中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;這種動态擷取資訊以及動态調用對象方法的功能稱為 Java 語言的反射機制。簡單來說,反射機制指的是程式在運作時能夠擷取自身的資訊。在 Java 中,隻要給定類的名字,就可以通過反射機制來獲得類的所有資訊。

Java 反射機制在伺服器程式和中間件程式中得到了廣泛運用。在伺服器端,往往需要根據客戶的請求,動态調用某一個對象的特定方法。此外,在 ORM 中間件的實作中,運用 Java 反射機制可以讀取任意一個 JavaBean 的所有屬性,或者給這些屬性指派。

Java反射機制是什麼?

Java 反射機制主要提供了以下功能,這些功能都位于

java.lang.reflect

包。

  • 在運作時判斷任意一個對象所屬的類。
  • 在運作時構造任意一個類的對象。
  • 在運作時判斷任意一個類所具有的成員變量和方法。
  • 在運作時調用任意一個對象的方法。
  • 生成動态代理。

要想知道一個類的屬性和方法,必須先擷取到該類的位元組碼檔案對象。擷取類的資訊時,使用的就是 Class 類中的方法。是以先要擷取到每一個位元組碼檔案(.class)對應的 Class 類型的對象.

衆所周知,所有 Java 類均繼承了 Object 類,在 Object 類中定義了一個 getClass() 方法,該方法傳回同一個類型為 Class 的對象。例如,下面的示例代碼:

Class labelCls = label1.getClass(); // label1為 JLabel 類的對象
           

利用 Class 類的對象 labelCls 可以通路 labelCls 對象的描述資訊、JLabel 類的資訊以及基類 Object 的資訊。表 1 列出了通過反射可以通路的資訊。

表 1 反射可通路的常用資訊

類型 通路方法 傳回值類型 說明
包路徑 getPackage() Package 對象 擷取該類的存放路徑
類名稱 getName() String 對象 擷取該類的名稱
繼承類 getSuperclass() Class 對象 擷取該類繼承的類
實作接口 getlnterfaces() Class 型數組 擷取該類實作的所有接口
構造方法 getConstructors() Constructor 型數組 擷取所有權限為 public 的構造方法
getDeclaredContruectors() Constructor 對象 擷取目前對象的所有構造方法
方法 getMethods() Methods 型數組 擷取所有權限為 public 的方法
getDeclaredMethods() Methods 對象 擷取目前對象的所有方法
成員變量 getFields() Field 型數組 擷取所有權限為 public 的成員變量
getDeclareFileds() Field 對象 擷取目前對象的所有成員變量
内部類 getClasses() Class 型數組 擷取所有權限為 public 的内部類
getDeclaredClasses() Class 型數組 擷取所有内部類
内部類的聲明類 getDeclaringClass() Class 對象 如果該類為内部類,則傳回它的成員類,否則傳回 null

如表 1 所示,在調用 getFields() 和 getMethods() 方法時将會依次擷取權限為 public 的字段和變量,然後将包含從超類中繼承到的成員變量和方法。而通過 getDeclareFields() 和 getDeclareMethod() 隻是擷取在本類中定義的成員變量和方法。

Java 反射機制的優缺點

優點:

  • 能夠運作時動态擷取類的執行個體,大大提高系統的靈活性和擴充性。
  • 與 Java 動态編譯相結合,可以實作無比強大的功能。
  • 對于 Java 這種先編譯再運作的語言,能夠讓我們很友善的建立靈活的代碼,這些代碼可以在運作時裝配,無需在元件之間進行源代碼的連結,更加容易實作面向對象。

缺點:

  • 反射會消耗一定的系統資源,是以,如果不需要動态地建立一個對象,那麼就不需要用反射;
  • 反射調用方法時可以忽略權限檢查,擷取這個類的私有方法和屬性,是以可能會破壞類的封裝性而導緻安全問題。

Java 反射機制在一般的 Java 應用開發中很少使用,即便是 Java EE 階段也很少使用。