一、靜態載入類和動態載入類
靜態載入類:new建立物件,是靜態載入類,在編譯時刻就需要載入所有可能用到的類
動態載入類:在執行時載入 反射是一種動態載入類的機制
二、反射的優劣
優點:執行時型別的判斷、動態載入類:提高了程式碼的靈活性,可以在不修改原始碼的情況下修改功能
缺點:存在效能瓶頸:需要進行安全性檢查、反射相當於一系列解釋操作,比直接的Java程式碼慢
三、透過反射了解泛型的本質
1、泛型只在編譯期間生效
public class Test { public static void main(String[] args) { // 1、檢驗泛型擦除 List list1 = new ArrayList(); List
執行結果:true
2、集合泛型是為了型別檢查,避免錯誤輸入
List
編譯錯誤:int無法轉換為java。lang。String
3、可以透過反射繞過泛型的檢查,新增不同型別的元素
List
執行結果:2
可以看到,由於泛型的型別檢查只在編譯時有效,利用反射的動態載入原理,可以繞過泛型的檢查,往集合裡新增不同型別的元素
四、反射的應用
1、載入資料庫驅動
// DriverManager。registerDriver(new com。mysql。cj。jdbc。Driver());Class。forName(“com。mysql。cj。jdbc。Driver”);
2、xml或properties等配置檔案載入
Spring透過XML配置模式裝載Bean的過程
將程式中所有XML或properties配置檔案載入入記憶體
Java類裡面解析xml或者properties裡面的內容,得到對應實體類的位元組碼字串以及相關的屬性資訊
使用反射機制,根據這個字串獲得某個類的Class例項
動態配置例項的屬性
配置檔案
className=com。example。reflectdemo。TestInvokemethodName=printlnState
實體類
public class TestInvoke { private void printlnState(){ System。out。println(“I am fine”); }}
解析配置檔案內容
// 解析xml或properties裡面的內容,得到對應實體類的位元組碼字串以及屬性資訊public static String getName(String key) throws IOException { Properties properties = new Properties(); FileInputStream in = new FileInputStream(“D:\IdeaProjects\AllDemos\language-specification\src\main\resources\application。properties”); properties。load(in); in。close(); return properties。getProperty(key);}
利用反射獲取實體類的Class例項,建立實體類的例項物件,呼叫方法
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, InstantiationException { // 使用反射機制,根據這個字串獲得Class物件 Class<?> c = Class。forName(getName(“className”)); System。out。println(c。getSimpleName()); // 獲取方法 Method method = c。getDeclaredMethod(getName(“methodName”)); // 繞過安全檢查 method。setAccessible(true); // 建立例項物件 TestInvoke testInvoke = (TestInvoke)c。newInstance(); // 呼叫方法 method。invoke(testInvoke);}
執行結果:
作者:bkpp976
連結:https://juejin。cn/post/7042974349883604999