誰能給我講一講Java中反射機制?

決戰知春路


在學習 Java 反射之前,先讓我們看看這幾個概念。


01. 解釋型語言和編譯型語言

解釋型語言:不需要編譯,在運行的時候逐行翻譯解釋;修改代碼時可以直接修改,可以快速部署,不過性能上會比編譯型語言稍差;比如 JavaScript、Python ;

編譯型語言:需要通過編譯器將源代碼編譯成機器碼才能執行;編譯之後如果需要修改代碼,在執行之前就需要重新編譯。比如 C 語言;

Java 嚴格來說也是編譯型語言,但又介於編譯型和解釋型之間;Java 不直接生成機器碼而是生成中間碼:編譯期間,是將源碼交給編譯器生成 class 文件(字節碼),這個過程中只做了翻譯的工作,並沒有把代碼放入內存運行;當進入運行期,字節碼才被 Java 虛擬機加載、解釋成機器語言並運行。


02. 動態語言和靜態語言

動態語言:是指程序在運行時可以改變自身結構,在運行時確定數據類型,一個對象是否能執行某操作,只取決於它有沒有對應的方法,而不在乎它是否是某種類型的對象;比如 JavaScript、Python。

靜態語言:相對於動態語言來說,在編譯時變量的數據類型就已經確定(使用變量之前必須聲明數據類型),在編譯時就會進行類型是否匹配;比如 C 語言、Java ;


03. 反射的概念

Java 反射機制:在運行過程中,對於任意一個類,都能知道其所有的屬性和方法;對於任意一個對象,都能調用其屬性和方法;這種動態獲取類信息和調用對象方法的功能,就是 Java 反射機制。

既然反射裡面有一個“反”字,那麼我們先看看何為“正”。

在 Java 中,要使用一個類中的某個方法,“正向”都是這樣的:

那麼反向(反射)要如何實現?

兩段代碼執行的結果是一樣的,但是“正向”代碼在編譯前,就已經明確了要運行的類是什麼(ArrayList),而第二段代碼,只有在代碼運行時,才知道運行的類是 java.util.ArrayList。


04. 反射的作用

講到這裡,有些同學可能會有疑問:“反射有什麼用?我明明都已經知道了要使用的類是 ArrayList ,我不能直接 new 一個對象然後執行裡面的方法麼?”

當然可以!不過很多場景中,在代碼運行之前並不知道需要使用哪個類,或者說在運行的時候才決定使用哪個類;

比如有這麼一個功能:“調用阿里雲的人臉識別 API ”;這還不簡單,參考對方的 API 文檔,很快就能實現。

上線一個月後,領導說:“咱公司開始和騰訊雲合作了,人臉識別的接口改一下吧”。

修改上線運行了兩個月,領導說:“換回來吧”... ...

當然有聰明的程序員會想到設置一個開關配置,讓開關決定走哪段代碼邏輯,如果領導哪天想變成亞馬遜雲的服務,繼續寫 if-else 就好了:


不過還有一種更好的方法:

1. 定義一個接口:


2. 多個實現類:


3. 在調用人臉識別功能的代碼中:


如果上面這個例子,你依然覺得在調用方法中做 if-else 判斷,和使用反射實現並沒有差太多,但是如果程序員 A 提供接口,程序員 B 提供實現,程序員 C 寫客戶端呢?

回憶一下 JDBC 的使用,比如創建一個連接:


其中:

  • 程序員 A 提供接口:Oracle 公司(之前的 Sun)提供 JDBC 標準(接口)。
  • 程序員 B 提供實現:各個數據庫廠商提供針對自家數據庫的實現。
  • 程序員 C 寫客戶端:我等碼農在 Java 中敲代碼訪問數據庫。

總結一下Java 反射的作用:可以設計出更為通用和靈活的架構,很多框架為了保證其通用性,可以根據配置加載不用的類,這時候要用到反射。除此之外:

  • 動態代理:在不改變目標對象方法的情況下對方法進行增強,比如使用 AOP 攔截某些方法打印日誌,這就需要通過反射執行方法中的內容。
  • 註解:利用反射機制,獲取註解並執行對應的行為。


05. 用反射的用法

上文中我們知道了 Java 運行期的源文件是 class 文件(字節碼),所以要使用反射,那麼就需要獲取到字節碼文件對象,在 Java 中,獲取字節碼文件對象有三種方式:

  • 調用某個類的 class 屬性:類名.class
  • 調用對象的 getClass() 方法:對象.getClass()
  • 使用 Class 類中的 forName() 靜態方法:Class.forName(類的全路徑) ,建議使用這種方法

java.lang.reflect 類庫提供了對反射的支持:

  • Field :可以使用 get 和 set 方法讀取和修改對象的屬性;
  • Method :可以使用 invoke() 方法調用對象中的方法;
  • Constructor :可以用 newInstance() 創建新的對象。


06. 反射的優缺點

  • 優點:在運行時動態獲取類和對象中的內容,極大地提高系統的靈活性和擴展性;誇張一些說,反射是框架設計的靈魂。

  • 缺點:會有一定的性能損耗,JVM 無法對這些代碼進行優化;破壞類的封裝性。

總之,可能大家在平時的開發過程中,感覺自己並沒有寫過反射相關的代碼,但是在我們用到的各種開源框架中,反射無處不在。

我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注;關注我後,可私信發送數字【1】,獲取海量學習資料。


會點代碼的大叔


Java反射的概念

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

反射的作用

我們都知道程序員編寫的Java代碼必須編譯成.class文件才能在JVM中運行,如何不符合JVM的規範,則會在編譯期間報錯。那麼反射的意思和反編譯差不多,就是根據

.class

文件獲取這個類的所有屬性和方法,且可以調用它的方法。

正常方式:通過完整的類名 > 通過new實例化 > 取得實例化對象

反射方式:實例化對象 > getClass()方法 > 通過完整的類名


示例

創建一個用於測試的類:

TestReflect.java

獲取類的三種方式:

獲取類的所有屬性:

獲取類的所有方法:

獲取所有的構造方法:

動態調用方法:


反射的應用場景

  1. Spring框架中的IoC:控制反轉,依賴注入
  2. 通過反射機制獲取註解信息
  3. 逆向代碼,反編譯
  4. 動態代理
  5. AOP
  6. ...

以上就是Java反射的基礎入門知識,希望對題主的問答有所幫助~


java架構設計


沒人請,自己搬小板凳過來的,您的問題什麼事Java反射機制?

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


宣銘科技


Java的反射就是在運行時通過訪問class文件來動態的執行某些方法。


十萬個為神麼


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

我之前寫過一篇關於Java創建對象的文章,裡面提到了兩種Java的反射機制。

第一種:利用

Class.newInstance

方式創建對象

第二種:利用

Constructor.newInstance

方式創建對象

Class.newInstance你內部也是調用了Constructor.newInstance。所以大多數的開源框架都會使用Constructor來實現反射。

希望對你有用!


JAVA小學生


java的反射機制主要是指程序可以訪問,檢測和修改它本身狀態或行為的一種能力,並能根據自身行為的狀態和結果,調整或修改應用所描述行為的狀態和相關的語義。


分享到:


相關文章: