Hello,今天給各位童鞋們分享的是Java反射,趕緊拿出小本子記下來吧反射概述什麼是反射將類的各個組成部分封裝為其他物件的過程就叫做 反射,其中 組成部分指的是我們類的 成員變
2021-06-25 15:30:06
Hello,今天給各位童鞋們分享的是Java反射,趕緊拿出小本子記下來吧
反射概述
什麼是反射
將類的各個組成部分封裝為其他物件的過程就叫做 反射,其中 組成部分指的是我們類的 成員變數(Field)、構造方法(Constructor)、成員方法(Method)。
使用反射的優缺點
優點在程式運行過程中可以操作類物件,增加了程式的靈活性;解耦,從而提高程式的可擴展性,提高程式碼的複用率,方便外部呼叫;對於任何一個類,當知道它的類名後,就能夠知道這個類的所有屬性和方法;而對於任何一個物件,都能夠呼叫它的一個任意方法。缺點效能問題:Java 反射中包含了一些動態類型,JVM 無法對這些動態程式碼進行優化,因此通過反射來操作的方式要比正常操作效率更低。安全問題:使用反射時要求程式必須在一個沒有安全限制的環境中運行,如果程式有安全限制,就不能使用反射。程式健壯性:反射允許程式碼執行一些平常不被允許的操作,破壞了程式結構的抽象性,導致平臺發生變化時抽象的邏輯結構無法被識別。Class 物件的獲取及使用
獲取 Class 物件的方式
Class.forName("全類名")原始碼階段,它能將位元組碼檔案載入進記憶體中,然後返回 Class 物件,多用於 配置檔案 中,將類名定義在配置檔案中,通過讀取配置檔案來載入類。
2.類名.class
類物件階段,通過類名的 class 屬性來獲取,多用於 參數的傳遞。
3.物件.getClass()
運行時階段,getClass() 定義在 Object 類中,表明所有類都能使用該方法,多用於 物件的獲取位元組碼的方式。
我們首先定義一個 Person 類,用於後續反射功能的測試;
定義好 Person 類之後,我們嘗試用 3 種不同的方式來獲取 Class 物件,並比較它們是否相同。
上述程式碼中,會發現最後輸出的比較結果返回的是兩個 true,說明通過上述三種方式獲取的 Class 物件都是同一個,同一個位元組碼檔案(*.class)在一次運行過程中只會被載入一次。
Class 物件的使用
獲取成員變數
Field[] getFields()
回顧下我們的 Person 類,可以發現 id、grade 成員變數都是被 public 所修飾的,說明該方法是用於獲取類中所有被 public 所修飾的成員變數(包括父類)。
Field getField(String name)
從上面的結果分析可知,該方法只能用於獲取類中指定名稱的 public 所修飾的成員變數,對於 protected、private 所修飾的成員變數,該方法是無法獲取的(包括父類)。而獲取或設定成員變數值時,可以通過 get/set 方法來操作,具體操作方法如下。
Field[] getDeclaredFields()
觀察上面的結果可知,該方法可用於獲取所有的成員變數,不用考慮修飾符的限制(不包括父類)。
Field getDeclaredField(String name)
觀察上面的結果可知,該方法可用於獲取指定的成員變數,不用考慮成員變數修飾符的限制(不包括父類)。但是在利用 set、get 方法來獲取和設定 private、protected 修飾的成員變數時,需要利用 setAccessible() 來忽略訪問全新啊修飾符的安全檢查,否則程式將會報錯。
獲取構造方法
Constructor<?>[] getConstructors()類似於通過 Class 例項來獲取成員變數,該方法用於獲取所有 public 所修飾的構造方法(包括父類);Constructor<T> getConstructor(類<?>... parameterTypes)該方法用於獲取某一指定參數類型後的 public 所修飾的構造方法(包括父類);
Constructor<?>[] getDeclaredConstructors()該方法用於獲取所有 public 所修飾的構造方法(不包括父類);
Constructor<T> getDeclaredConstructor(類<?>... parameterTypes)該方法用於獲取某一指定參數類型後的 public 所修飾的構造方法(不包括父類);
而獲取到構造方法之後,我們就可以利用 newInstance() 方法來創建類的例項。特殊的,如果我們的構造方法是無參的,此時則可以直接利用 Class.newInstance() 來構造例項。
獲取成員方法
Method[] getMethods()用於獲取當前類的所有 public 所修飾的成員方法(包括父類)。
Method getMethod(String name, 類<?>... parameterTypes)用於獲取當前類的某一個指定名稱 public 所修飾的成員方法(包括父類)。
Method[] getDeclaredMethods()用於獲取當前類的所有 public 所修飾的成員方法(不包括父類)。
Method getDeclaredMethods(String name, 類<?>... parameterTypes)用於獲取當前類的某一個指定名稱 public 所修飾的成員方法(不包括父類)。
而當我們獲取到類的成員方法後,如果要執行某一個方法,可以使用 invoke() 方法來執行該方法。
獲取類名
String getName()從上述程式的結果可知,當我們獲取到 Class 物件之後,如果不知道類的全名,就可以使用 getName() 來獲取該類的全名。
反射例項
假設我們有如下需求:在不改變類的程式碼的前提下,我們能夠創建任意類的物件,並執行其中的方法。
此時,我們可以通過 配置檔案 + 反射的方式來實現這一效果,而這也就是我們現在所用框架中的基礎,當我們使用反射後,只需要通過修改配置檔案中的內容就能夠不用去改程式碼就實現對應的功能。
假設我們有兩個類,一個 Student,一個 Teacher,兩者的定義如下;
要實現我們的需求,通常需要如下步驟:
將要創建物件的全類名和要執行的方法都配置在配置檔案中;定義的配置檔案 prop.properties ,其中主要內容包括 className 和 methodName 兩個屬性,分別代表類的全類名和要呼叫方法的名字。一個具體例項如下,分別代表名為 Student 的類和名為 study 的方法。
2.然後在主方法中載入讀取配置檔案;
3.利用反射技術將類載入到記憶體中;
4.接著利用 newInstance() 方法創建物件;
5.最後則是利用 invoke() 方法來執行方法;
將整個流程彙總起來就是:
此時,我們只需要改動配置檔案 prop.properties 中的配置即可輸出不同結果;
好啦,今天的文章就到這裡了,希望能夠幫助到螢幕前迷茫的你們
如何獲取Java學習資料?
轉發分享此文,後臺私信小編:「 資料 」即可獲取。注意是私信,因為檔案比較大,所以要加好友,免費,不花錢(注:轉發分享,感謝大家
相關文章
Hello,今天給各位童鞋們分享的是Java反射,趕緊拿出小本子記下來吧反射概述什麼是反射將類的各個組成部分封裝為其他物件的過程就叫做 反射,其中 組成部分指的是我們類的 成員變
2021-06-25 15:30:06
機器之心報道作者:杜偉當今時代,AI 無處不在,對於企業來說更是如此。企業有時想要在混合雲業務中加入 AI 功能,有時又想要發揮邊緣計算的效用,但自身 AI 基礎設施無法提供支援怎
2021-06-25 15:29:32
CVPR 2021近日如期舉行,中國人工智慧「頭雁」百度持續綻放高光:不僅在計算機視覺領域多個細分賽道獲得10個冠軍,更保持多篇高質量論文入選,主辦了一場重量級學術workshop和一場T
2021-06-25 15:29:26
不可否認,如今國內手機市場風起雲湧,小米能夠短時間內在銷量上風頭無兩,是因為其明確的市場定位和不錯的使用者體驗。雖然如今的小米手機衝擊到了高階旗艦市場,並且系統方面的口
2021-06-25 15:28:35
IT之家 6 月 25 日訊息 知名蘋果訊息洩露者 @Kang 昨晚在微博發文稱,蘋果公司最近委託一家律師事務所向一些洩密者發出告誡信。據稱,信中告誡洩密者,他們不得洩露未釋出的蘋果
2021-06-25 15:28:24
目前整合灶已經成為新一代的高階廚電,空間佔用小,整合功能多, 淨煙效果出色。帥豐作為整合灶行業的知名品牌,在行業和消費者群體中都有著較好的影響力,本期內容我們就和大家一起
2021-06-25 15:28:03