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 資料庫驅動,更改資料庫時就僅需簡單的更改設定檔了,這樣就不需要重新編譯代碼了,但好像還需要重新啟動生產環境。哦,如果想不重新啟動生產環境來切換資料庫也是可以的(不考慮任何效率),自行造輪子咯。
這裡用反射和不用反射的區別在於,是否要重新編譯一遍。以上是我的想法和見解,因為最近也在瞭解反射到底是個什麼東西。有不同看法和見解,歡迎來"戰"