Java反射機制--是什麼,為什麼,怎麼用。。本站提示廣大學習愛好者:(Java反射機制--是什麼,為什麼,怎麼用。)文章只能為提供參考,不一定能成為您想要的結果。以下是Java反射機制--是什麼,為什麼,怎麼用。正文
往往當我們面對一項新的知識時,我們往往需要知道三個方面,它是什麼,它能做什麼,它比原有知識強在哪裡,我們該怎麼使用它。當你能夠解決這些問題時,便意味著你已經對這項知識入門了。
一、是什麼
Java Reflaction in Action有這麼一句話,可以解釋。反射是運行中的程序檢查自己和軟件運行環境的能力,它可以根據它發現的進行改變。通俗的講就是反射可以在運行時根據指定的類名獲得類的信息。
二、為什麼
我們為什麼要使用反射,它的作用是什麼,它在實際的編程中有什麼應用。
首先我們先明確兩個概念,靜態編譯和動態編譯。
靜態編譯:在編譯時確定類型,綁定對象,即通過。
動態編譯:運行時確定類型,綁定對象。動態編譯最大限度發揮了java的靈活性,體現了多
態的應用,有以降低類之間的藕合性。
我們可以明確的看出動態編譯的好處,而反射就是運用了動態編譯創建對象。
那麼我們再來看看實際中反射又有什麼好處那?
往往對比能更加直觀的向我們展示兩者的不同。
先從某個代碼案例上來解釋(套用一篇博文的一個例子:http://blog.csdn.net/justdoit_potato/article/details/51011843)
若是不用反射,它是這樣的
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 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(); } }
可以發現,每當我們要添加一種新的水果的時候,我們將不得不改變Factory中的源碼,而往往改變原有正確代碼是一種十分危險的行為。而且隨著水果種類的增加,你會發現你的factory類會越來越臃腫,
不得不說這是一種十分--的做法。(初學者可能會問,我們為什麼不直接在main方法中new水果那,我們可能會需要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(); } } }
在出現新品種水果的時候,你完全不用去修改原有代碼。
從上面的案例中,我們可以清楚的體會到反射的優越性。
那麼有的人又會問,這個例子能完全明白,但是如果放到實際的編程,應用中,我們又會在什麼情況下用到反射那?
舉一個看到過的例子,在實際開發中,我們需要把一個包中的class new出來,但是這個包中的類總是需要變動,那麼怎麼辦,難道總是修改main方法中xxx=new xxx()嗎。這樣無疑是麻煩的。而運用反射。我們可以相應的增加一個配置文件,在裡面記錄包中所有的類名,包中類增加時就加一個類名,刪除時就刪除一個類名。讓main方法去讀取這個配置文件中的類名,通過反射獲得實例,完全不用我們去修改main方法中的代碼。
反射還有什麼用那?他甚至可以修改其他類中的私有屬性。android開發中,我們需要改變一個私有標志位的時候,android源碼並沒有提供set方法,我們又不能改變源碼,怎麼辦,反射可以完美解決這個問題。
說了這麼多,那麼我們的開發中,為什麼不全部都用反射那?一個原因,開銷,它的開銷是什麼昂貴的,隨意盡量在最需要的地方使用反射。
三、怎麼用
說完是什麼,為什麼,我們必然需要掌握如何使用反射,先看反射中涉及了那些方法。
Class c=Class.forName("className");注明:className必須為全名,也就是得包含包名,比如,cn.netjava.pojo.UserInfo;
Object obj=c.newInstance();//創建對象的實例
OK,有了對象就什麼都好辦了,想要什麼信息就有什麼信息了。
獲得構造函數的方法
Constructor getConstructor(Class[] params)//根據指定參數獲得public構造器
Constructor[] getConstructors()//獲得public的所有構造器
Constructor getDeclaredConstructor(Class[] params)//根據指定參數獲得public和非public的構造器
Constructor[] getDeclaredConstructors()//獲得public的所有構造器
獲得類方法的方法
Method getMethod(String name, Class[] params),根據方法名,參數類型獲得方法
Method[] getMethods()//獲得所有的public方法
Method getDeclaredMethod(String name, Class[] params)//根據方法名和參數類型,獲得public和非public的方法
Method[] getDeclaredMethods()//獲得所以的public和非public方法
獲得類中屬性的方法
Field getField(String name)//根據變量名得到相應的public變量
Field[] getFields()//獲得類中所以public的方法
Field getDeclaredField(String name)//根據方法名獲得public和非public變量
Field[] getDeclaredFields()//獲得類中所有的public和非public方法
看到這些方法,你就可以明白,反射是多麼的強大了,當你正確使用這些方法的時候,基本上是掌握了反射的技巧。
參考博文:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html