更新時(shí)間:2020-11-23 17:56:41 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1601次
在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對象方法的功能稱為java語言的反射機(jī)制。通俗的講就是反射可以在運(yùn)行時(shí)根據(jù)指定的類名獲得類的信息。那么我們為什么用反射機(jī)制呢?
首先我們先明確兩個(gè)概念,靜態(tài)編譯和動(dòng)態(tài)編譯。
靜態(tài)編譯:在編譯時(shí)確定類型,綁定對象,即通過。
動(dòng)態(tài)編譯:運(yùn)行時(shí)確定類型,綁定對象。動(dòng)態(tài)編譯最大限度發(fā)揮了java的靈活性,體現(xiàn)了多態(tài)的應(yīng)用,有以降低類之間的藕合性。
我們可以明確的看出動(dòng)態(tài)編譯的好處,而反射就是運(yùn)用了動(dòng)態(tài)編譯創(chuàng)建對象。那么我們再來看看實(shí)際中反射又有什么好處那?
往往對比能更加直觀的向我們展示兩者的不同。
先從某個(gè)代碼案例上來解釋:
若是不用反射,它是這樣的
interface fruit{
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
// 構(gòu)造工廠類
// 也就是說以后如果我們在添加其他的實(shí)例的時(shí)候只需要修改工廠類就行了
class Factory{
public static fruit getInstance(String fruitName){
fruit f=null;
if("Apple".equals(fruitName)){
f=new Apple();
}
if("Orange".equals(fruitName)){
f=new Orange();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Orange");
f.eat();
}
}
可以發(fā)現(xiàn),每當(dāng)我們要添加一種新的水果的時(shí)候,我們將不得不改變Factory中的源碼,而往往改變原有正確代碼是一種風(fēng)險(xiǎn)很高的行為。而且隨著水果種類的增加,你會(huì)發(fā)現(xiàn)你的factory類代碼會(huì)越來越臃腫,不得不說這是一種性價(jià)比很低的做法。(初學(xué)者可能會(huì)問,我們?yōu)槭裁床恢苯釉趍ain方法中new水果那,我們可能會(huì)需要getInstance方法做一些別的事情。。。所以不直接new);而反射無疑是一種聰明的辦法,看代碼。
interface fruit{
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
class Factory{
public static fruit getInstance(String ClassName){
fruit f=null;
try{
f=(fruit)Class.forName(ClassName).newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Reflect.Apple");
if(f!=null){
f.eat();
}
}
}
在出現(xiàn)新品種水果的時(shí)候,你完全不用去修改原有代碼。
從上面的案例中,我們可以清楚的體會(huì)到反射的優(yōu)越性。
那么有的人又會(huì)問,這個(gè)例子能完全明白,但是如果放到實(shí)際的編程,應(yīng)用中,我們又會(huì)在什么情況下用到反射那?
舉一個(gè)看到過的例子,在實(shí)際開發(fā)中,我們需要把一個(gè)包中的class new出來,但是這個(gè)包中的類總是需要變動(dòng),那么怎么辦,難道總是修改main方法中xxx=new xxx()嗎。這樣無疑是麻煩的。而運(yùn)用反射。我們可以相應(yīng)的增加一個(gè)配置文件,在里面記錄包中所有的類名,包中類增加時(shí)就加一個(gè)類名,刪除時(shí)就刪除一個(gè)類名。讓main方法去讀取這個(gè)配置文件中的類名,通過反射獲得實(shí)例,完全不用我們?nèi)バ薷膍ain方法中的代碼。
除此之外,Java反射甚至可以修改其他類中的私有屬性。在Android開發(fā)中,我們需要改變一個(gè)私有標(biāo)志位的時(shí)候,Android源碼并沒有提供set方法,我們又不能改變源碼,這個(gè)時(shí)候反射也可以完美地解決這個(gè)問題。
經(jīng)過以上的介紹對于為什么用java反射機(jī)制,有了或多或少的認(rèn)識,但事實(shí)上在我們的開發(fā)中,不全部都用反射機(jī)制?原因就是用java反制機(jī)制開銷很大,費(fèi)用十分昂貴,所以我們盡量在最需要的地方合理地使用反射。在本站的Java基礎(chǔ)教程中,對Java反射進(jìn)行了十分全面的講解,想要徹底弄懂Java反射的小伙伴一定不要錯(cuò)過。

初級 202925

初級 203221

初級 202629

初級 203743