1. 程式人生 > >Java反射機制--是什麼,為什麼,怎麼用

Java反射機制--是什麼,為什麼,怎麼用

1.反射是什麼

首先看書要理解反射,很難完全理解,這關係到Java的語言特性,jvm的記憶體細節,當初我看反射,就像高票答案那樣,照著寫一遍,結果是你並沒有理解,你只是照貓畫虎,要想真正理解,我建議題主,不斷深入探究,當你踩得足夠深回過頭來,你會柳暗花明!

這裡我不打算像別的答案上來就上程式碼,給你講怎麼用,是啥是啥,老實說那樣比較像培訓java程式設計師的感覺,一點對知識的好奇心都沒有,如果是想速成反射的,大家看別的答案吧。

寫答案,可能會有預設知識現象,就是有些知識點,我知道,但你不知道,可以評論!這裡我試著簡單粗暴地解釋一波!

首先我們瞭解一下JVM,什麼是JVM,Java的虛擬機器,java之所以能跨平臺就是因為這個東西,你可以理解成一個程序,程式,只不過他的作用是用來跑你的程式碼的。上圖是java的記憶體模型,我們關注的點,一個方法區,一個棧,一個堆,初學的時候老師不深入的話只告訴你java的記憶體分為堆和棧,易懂點吧!

假如你寫了一段程式碼:Object o=new Object();

運行了起來!

首先JVM會啟動,你的程式碼會編譯成一個.class檔案,然後被類載入器載入進jvm的記憶體中,你的類Object載入到方法區中,建立了Object類的class物件到堆中,注意這個不是new出來的物件,而是類的型別物件,每個類只有一個class物件,作為方法區類的資料結構的介面。jvm建立物件前,會先檢查類是否載入,尋找類對應的class物件,若載入好,則為你的物件分配記憶體,初始化也就是程式碼:new Object()。

上面的流程就是你自己寫好的程式碼扔給jvm去跑,跑完就over了,jvm關閉,你的程式也停止了。

為什麼要講這個呢?因為要理解反射必須知道它在什麼場景下使用。

題主想想上面的程式物件是自己new的,程式相當於寫死了給jvm去跑。假如一個伺服器上突然遇到某個請求哦要用到某個類,哎呀但沒載入進jvm,是不是要停下來自己寫段程式碼,new一下,哦啟動一下伺服器,(腦殘)!

反射是什麼呢?當我們的程式在執行時,需要動態的載入一些類這些類可能之前用不到所以不用載入到jvm,而是在執行時根據需要才載入,這樣的好處對於伺服器來說不言而喻,舉個例子我們的專案底層有時是用mysql,有時用oracle,需要動態地根據實際情況載入驅動類,這個時候反射就有用了,假設 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection這兩個類我們要用,這時候我們的程式就寫得比較動態化,通過Class tc = Class.forName("com.java.dbtest.TestConnection");通過類的全類名讓jvm在伺服器中找到並載入這個類,而如果是oracle則傳入的引數就變成另一個了。這時候就可以看到反射的好處了,這個動態性就體現出java的特性了!舉多個例子,大家如果接觸過spring,會發現當你配置各種各樣的bean時,是以配置檔案的形式配置的,你需要用到哪些bean就配哪些,spring容器就會根據你的需求去動態載入,你的程式就能健壯地執行。

2.使用場景

這個場景的簡單例子。

不用反射:

假設有個生產環境,資料庫連線是用的mysql,所以程式碼應該是這樣 ,以虛擬碼書寫,忽略細節
conn =new MysqlConnection()
然而,某一天突然要改成oracle。所以,這時要做的是改成
conn =new OracleConnection()
或者你機靈一點,新建一個配置檔案,裡面填mysql或oracle,然後程式碼中取得配置檔案的字串,if是 mysql就 conn =new MysqlConnection() 是oracle就 conn =new OracleConnection,
然後。最重要的是。你要停掉生產環境,重新把java程式碼用javac編譯一遍,再把編譯後的class檔案把生產環境給起起來。

讓我們再來看看用反射,
最開始,如果我們就考慮到會有時切換資料庫,我們寫成配置檔案,然後用Class.forName(str)什麼的來new 資料庫驅動,更改資料庫時就僅需簡單的更改配置檔案了,這樣就不需要重新編譯程式碼了,但好像還需要重新啟動生產環境。哦,如果想不重新啟動生產環境來切換資料庫也是可以的(不考慮任何效率),自行造輪子咯。
這裡用反射和不用反射的區別在於,是否要重新編譯一遍。以上是我的想法和見解,因為最近也在瞭解反射到底是個什麼東西。有不同看法和見解,歡迎來"戰"