一篇文章帶你了解一些Java反射的學(xué)習(xí)記錄
一、反射概述
- 反射允許程序在運(yùn)行中獲取類的內(nèi)部信息,例如構(gòu)造器、成員變量、成員方法等
- 類加載之后,在堆中生成一個(gè)Class類的對象(一個(gè)類只有一個(gè)Class對象),這個(gè)對象包含類的完整結(jié)構(gòu)信息
二、入門案例
通過配置文件中的內(nèi)容生成指定類的對象并調(diào)用指定方法
// re.properties className=com.javalearn.reflect.Cat methodName=hi
public class Cat {
private String name = "招財(cái)貓";
public void hi() {
System.out.println("hi:" + this.name);
}
}
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
// 1.properties對象加載配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src/main/resources/re.properties"));
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
System.out.println("類名:" + className);
System.out.println("方法名:" + methodName);
// 2.根據(jù)類名獲取Class類對象
// 獲取Class對象的三種方式:
// 1.類名.class
// 2.對象.getClass()
// 3.Class.forName(類名)
Class cls = Class.forName(className);
// 3.生成實(shí)例對象
Object o = cls.newInstance();
// 4.獲取方法
Method declaredMethod = cls.getDeclaredMethod(methodName);
// 5.方法.invoke(對象)
declaredMethod.invoke(o);
// 6.反射涉及的其他類
// 6.1Field成員變量
Field name = cls.getDeclaredField("name");
name.setAccessible(true); //private屬性需暴力反射
System.out.println(name.get(o));
// 6.2Constructor構(gòu)造器
Constructor constructor = cls.getConstructor(); //方法參數(shù)類型與構(gòu)造器的參數(shù)類型一致,不寫就是無參構(gòu)造器
Object o1 = constructor.newInstance();
System.out.println(o1);
}
}
三、反射原理圖
Java程序執(zhí)行的三個(gè)階段
- 將Java代碼編譯成字節(jié)碼
- 類加載器加載字節(jié)碼文件,在堆中生成Class類對象
- 運(yùn)行階段使用Class對象生成真正的Java類

反射可以做哪些事?
在運(yùn)行時(shí):
- 判斷任一對象所屬的類
- 構(gòu)造任一類的對象
- 得到任一類所具有的成員變量和方法
- 調(diào)用任一對象的成員變量和方法
- 生成動態(tài)代理
四、反射性能測試
反射基本上是解釋執(zhí)行,性能差
public class PerformanceDemo {
public static void main(String[] args) throws Exception {
tradition();
reflect();
}
private static void reflect() throws Exception {
Class cls = Class.forName("com.sankuai.yangjin.javalearn.reflect.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射耗時(shí):" + (end - start));
}
private static void tradition() {
Cat cat = new Cat();
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("傳統(tǒng)耗時(shí):" + (end - start));
}
}
優(yōu)化方式:
Method、Field、Constructor對象都有setAccessible()方法,可以將參數(shù)設(shè)置為true,表示在使用反射時(shí)取消訪問檢查,效果也就一般般
五、Class類
- Class類也是類,繼承Obejct類
- Class類對象不是new出來的,而是系統(tǒng)創(chuàng)建的
- 對于某個(gè)類的Class類對象,在內(nèi)存中只有一份,因?yàn)轭愔患虞d一次
- 每個(gè)類的實(shí)例都知道自己是由哪個(gè)Class實(shí)例生成,對象.getClass()
- 通過Class對象可以得到類的完整結(jié)構(gòu)
- Class對象是存放在堆的
- 類的字節(jié)碼二進(jìn)制數(shù)據(jù)(元數(shù)據(jù))存放在方法區(qū),包括方法代碼、變量名、方法名、訪問權(quán)限等
六、類加載
反射是Java實(shí)現(xiàn)動態(tài)語言的關(guān)鍵,通過反射實(shí)現(xiàn)類動態(tài)加載
- 靜態(tài)加載:編譯時(shí)加載相關(guān)的類,如果沒有相關(guān)的類則報(bào)錯(cuò),依賴太強(qiáng)
- 動態(tài)加載:運(yùn)行時(shí)加載需要的類,如果運(yùn)行時(shí)不用該類,那么即使該類不存在也不報(bào)錯(cuò)
將下面一段代碼通過javac 編譯時(shí),因?yàn)椴]有Dog類,所以編譯失??;但當(dāng)前同樣沒有Person類,卻不會由于沒有Person類而導(dǎo)致編譯失敗,因?yàn)槭莿討B(tài)加載,當(dāng)出現(xiàn)case "2"時(shí)才會加載該類
public class LoadDemo {
public static void main (String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
String num = scanner.next();
switch (num) {
case "1":
// 靜態(tài)加載
Dog dog = new Dog();
break;
case "2":
// 反射,動態(tài)加載
Class person = Class.forName("Person");
break;
default:
}
}
}
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
關(guān)于Mybatis中SQL節(jié)點(diǎn)的深入解析
這篇文章主要給大家介紹了關(guān)于Mybatis中SQL節(jié)點(diǎn)的深入解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03
springboot中報(bào)錯(cuò)Invalid character found in
這篇文章主要介紹了springboot中報(bào)錯(cuò)Invalid character found in the request的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
關(guān)于Mybatis-Plus?Update更新策略問題
這篇文章主要介紹了關(guān)于Mybatis-Plus?Update更新策略問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java Swing JProgressBar進(jìn)度條的實(shí)現(xiàn)示例
這篇文章主要介紹了Java Swing JProgressBar進(jìn)度條的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12

