有反射就有正射,直接new物件就叫正射,如下
Map<String, String> map = new HashMap<>();
map.put("蔡徐雞","唱跳rap籃球");
那反射是啥?我先不說反射是啥,概念啥的太虛幻我就不說了,把你繞蒙你這篇文章就白看了,直接舉例吧
接著看上面的正射,如果哪天你發現用LinkedHashMap效果更好,然后你噗呲噗呲修改代碼
Map<String, String> map = new LinkedHashMap<>();
map.put("蔡徐雞","唱跳rap籃球");
改完了編譯運行沒有bug,漂亮,老板可以上線了,噗呲噗呲打包上線;然而過了兩天你發現用LinkedHashMap會有隱患,還是得改回去用HashMap,成年人的崩潰如此簡單,但是聰明的你想到可以加個判斷,根據傳入的條件來決定用HashMap還是LinkedHashMap,于是…
public Map<String, String> getMap(String param) {
Map<String, String> map = null;
if (param.equals("HashMap")) {
map = new HashMap<>();
} else if (param.equals("LinkedHashMap")) {
map = new LinkedHashMap<>();
}
return map;
}
大功告成,這么難的邏輯都被你實作了,你現在很膨脹,甚至內心隱隱覺得這破公司已經容不下你這尊大佛了
但是某天老大看了你的代碼說:小張啊,這里你得用TreeMap;你又要噗呲噗呲改代碼,哦豁
------------------------------------------------------正經的分割線------------------------------------------------------
有沒有一種辦法可以讓你不修改代碼呢,of course、sure、必須~~滴
這時候反射就派上用場了
概念:反射是Java的一種機制,讓我們可以在運行時獲取類的資訊
作用:通過反射,我們可以在程式運行時動態創建物件,還能獲取到類的所有資訊,比如它的屬性、構造器、方法、注解等;
直接舉例吧
public Map<String, String> getMap(String className) {
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor();
return (Map<String, String>) constructor.newInstance();
}
這時候不管你需要什么Map,只要實作了Map介面,你都能通過getMap獲得,只需要傳入對應Map的全限定名,例如java.util.HashMap / java.util.LinkedHashMap
懂了沒,我問你懂了沒,沒懂的下面留言
------------------------------------------------------不正經的分割線------------------------------------------------------
java中反射的用法非常非常多,常見的有以下這幾個:
一、在運行時獲取一個類的 Class 物件
二、在運行時構造一個類的實體化物件
三、在運行時獲取一個類的所有資訊:變數、方法、構造器、注解
一、獲取class物件
三種方法
1、類名.class:這種獲取方式只有在編譯前已經宣告了該類的型別才能獲取到 Class 物件
Class<HashMap> hashMap= HashMap.class;
2、實體.getClass():通過實體化物件獲取該實體的 Class 物件
Map<String, String> hashMap = new HashMap<>();
Class<? extends Map> hashMapClass = hashMap.getClass();
3、Class.forName(“類的全限定名”):通過類的全限定名獲取該類的 Class 物件
Class<?> hashMap= Class.forName("java.util.HashMap");
拿到 Class物件就可以對它為所欲為了:剝開它的皮(獲取類資訊)、指揮它做事(呼叫它的方法),看透它的一切(獲取屬性),總之它在你面前就沒有隱私了,好羞羞,嚶~,
二、構造類的實體化物件
通過反射構造一個類的實體方式有2種:
1、Class 物件呼叫newInstance()方法
Class<?> hashMapClass = Class.forName("java.util.HashMap");
HashMap hashMapInstance = (HashMap) hashMapClass.newInstance();
注意:即使 HashMap已經顯式定義了構造方法,通過 newInstance() 創建的實體中,所有屬性值都是對應型別的初始值,因為 newInstance() 構造實體會呼叫默認無參構造器,
2、Constructor 構造器呼叫newInstance()方法
Class<?> hashMapClass = Class.forName("java.util.HashMap");
Constructor<?> constructor = hashMapClass.getConstructor();
constructor.setAccessible(true);
HashMap newInstance = (HashMap) constructor.newInstance("蔡徐雞", "唱跳rap籃球");
通過 getConstructor(Object… paramTypes) 方法指定獲取指定引數型別的 Constructor, Constructor 呼叫 newInstance(Object… paramValues) 時傳入構造方法引數的值,同樣可以構造一個實體,且內部屬性已經被賦值,
通過Class物件呼叫 newInstance() 會走默認無參構造方法,如果想通過顯式構造方法構造實體,需要提前從Class中呼叫getConstructor()方法獲取對應的構造器,通過構造器去實體化物件,
三、獲取類的所有資訊

1、獲取類中的變數(Field)
Field[] getFields():獲取類中所有被public修飾的所有變數 Field getField(String
name):根據變數名獲取類中的一個變數,該變數必須被public修飾 Field[]
getDeclaredFields():獲取類中所有的變數,但無法獲取繼承下來的變數 Field
getDeclaredField(String name):根據姓名獲取類中的某個變數,無法獲取繼承下來的變數
2、獲取類中的方法(Method)
Method[] getMethods():獲取類中被public修飾的所有方法
Method getMethod(String name, Class…<?>
paramTypes):根據名字和引數型別獲取對應方法,該方法必須被public修飾
Method[] getDeclaredMethods():獲取所有方法,但無法獲取繼承下來的方法
Method getDeclaredMethod(String name, Class…<?>
paramTypes):根據名字和引數型別獲取對應方法,無法獲取繼承下來的方法
3、獲取類的構造器(Constructor)
Constuctor[] getConstructors():獲取類中所有被public修飾的構造器 Constructor
getConstructor(Class…<?> paramTypes):根據引數型別獲取類中某個構造器,該構造器必須被public修飾
Constructor[] getDeclaredConstructors():獲取類中所有構造器 Constructor
getDeclaredConstructor(class…<?> paramTypes):根據引數型別獲取對應的構造器
反射的應用場景
1、Spring 實體化物件:當程式啟動時,Spring 會讀取組態檔applicationContext.xml并決議出里面所有的標簽實體化到IOC容器中,
2、反射 + 工廠模式:通過反射消除工廠中的多個分支,如果需要生產新的類,無需關注工廠類,工廠類可以應對各種新增的類,反射可以使得程式更加健壯,
3、JDBC連接資料庫:使用JDBC連接資料庫時,指定連接資料庫的驅動類時用到反射加載驅動類
良心建議,家里有條件的同學都把文中代碼在自己idea上跑一跑,真正用過以后面試官問到你才有底氣
如有雷同,純屬抄襲
嚶~
ok我話說完
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/256780.html
標籤:java
下一篇:十個Java基礎面試題(附答案)
