JAVA反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意方法和屬性;這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為java語言的反射機制。“反”,就要先了解“正”。一般先知道類,然后通過類產(chǎn)生實例化對象,而反射是通過對象找類。
反射機制一般用在框架類代碼編寫,所以平時在框架基礎(chǔ)上開發(fā)特性時一般用的比較少。
Class類是反射機制的基礎(chǔ)。反射機制是跟spring 和bean的基礎(chǔ)。
優(yōu)點:
使得系統(tǒng)框架具有高度的靈活性和擴展性。(反射是框架設(shè)計的靈魂)
缺點:
1)可能引入性能問題
2)使得程序的邏輯不再直觀
3)可移植性,因為反射依賴于java本身框架支持,如果移植到類似andriod平臺可能就支持的不好。
4)多線程高并發(fā)環(huán)境下可能引入問題。
所以,任何語言特性都不能濫用,要考慮是否需要另一種更合適的語言。
很多設(shè)計模式使用java的反射機制實現(xiàn)非常方便,甚至連客戶端的代碼都不需要修改。例如下面的簡單工廠的實現(xiàn),不需要停運行環(huán)境,只需要改配置文件即可實現(xiàn)不同類的生產(chǎn)。
import java.io.*;
import java.lang.reflect.InvocationTargetException;
class Animal {
void MyPrint(String str) {
System.out.println(str);
}
void Show() {
MyPrint("I'm Animal");
}
}
class Dog extends Animal {
@Override
void Show() {
MyPrint("I'm Dog");
}
}
class Cat extends Animal {
@Override
void Show() {
MyPrint("I'm Cat");
}
}
class AnimalFactory {
private static AnimalFactory factory = new AnimalFactory();
private AnimalFactory() {}
static AnimalFactory GetInst() {
return factory;
}
Animal Create() {
try {
// 替換成你自己的文件路徑
File file = new File("C:\\Users\\Administrator\\IdeaProjects\\demo2\\src\\test.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String animalName = reader.readLine();
Class<?> clazz = Class.forName(animalName);
Object obj = clazz.getDeclaredConstructors()[0].newInstance();
reader.close();
return (Animal) obj;
// 忽略異常處理
} catch (IOException e) {
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
} catch (ClassNotFoundException e) {
}
return null;
}
}
你可以在執(zhí)行過程中修改test.txt文件,可以看到工廠創(chuàng)建的類在及時地變化,而不需要重新編譯代碼,甚至不需要重新啟動程序。
I'm Cat
I'm Cat
I'm Cat
I'm Dog
重要的是要意識到反射沒有什么魔力。當你使用反射與未知類型的對象交互時,JVM 將查看該對象,并看到它屬于特定的類(就像普通的 RTTI)。在對其執(zhí)行任何操作之前,必須加載 Class 對象。因此,該特定類型的 .class 文件必須在本地計算機上或通過網(wǎng)絡(luò)對 JVM 仍然可用。因此,RTTI 和反射的真正區(qū)別在于,使用 RTTI 時,編譯器在編譯時會打開并檢查 .class 文件。換句話說,你可以用“正常”的方式調(diào)用一個對象的所有方法。通過反射,.class 文件在編譯時不可用;它由運行時環(huán)境打開并檢查。
反射機制的應(yīng)用場景:序列化,文檔提?。ㄒ婎惙椒ㄌ崛∑鳎?/p>
示例代碼倉庫: