Java反射的原理以及應用場景

一、靜態載入類和動態載入類

靜態載入類:new建立物件,是靜態載入類,在編譯時刻就需要載入所有可能用到的類

動態載入類:在執行時載入 反射是一種動態載入類的機制

Java反射的原理以及應用場景

二、反射的優劣

優點:執行時型別的判斷、動態載入類:提高了程式碼的靈活性,可以在不修改原始碼的情況下修改功能

缺點:存在效能瓶頸:需要進行安全性檢查、反射相當於一系列解釋操作,比直接的Java程式碼慢

三、透過反射了解泛型的本質

1、泛型只在編譯期間生效

public class Test { public static void main(String[] args) { // 1、檢驗泛型擦除 List list1 = new ArrayList(); List list2 = new ArrayList(); System。out。println(list1。getClass()==list2。getClass()); }}

執行結果:true

2、集合泛型是為了型別檢查,避免錯誤輸入

List list2 = new ArrayList();list2。add(“a”);list2。add(20);

編譯錯誤:int無法轉換為java。lang。String

3、可以透過反射繞過泛型的檢查,新增不同型別的元素

List list2 = new ArrayList();list2。add(“a”);Class<?> c = list2。getClass();Method method = c。getDeclaredMethod(“add”,Object。class);method。invoke(list2,20);System。out。println(list2。size());

執行結果: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);}

執行結果:

Java反射的原理以及應用場景

作者:bkpp976

連結:https://juejin。cn/post/7042974349883604999