////////////////////////2016-11-18///////////////////////////
int study_data(){
reflect:
簡介:
反射是一種強(qiáng)大的工具寂诱。它使您能夠創(chuàng)建靈活的代碼郭蕉,這些代碼可以在運(yùn)行時(shí)裝配骇钦,無需在組件之間進(jìn)行源代表鏈接。它允許運(yùn)行中的 Java 程序?qū)ψ陨磉M(jìn)行檢查,或者說“自審”,并能直接操作程序的內(nèi)部屬性。
一般的RTTI(運(yùn)行時(shí)類型識別)形式包括三種:
1.傳統(tǒng)的類型轉(zhuǎn)換凌停。如“(Apple)Fruit”,由RTTI確保類型轉(zhuǎn)換的正確性售滤,如果執(zhí)行了一個(gè)錯(cuò)誤的類型轉(zhuǎn)換,就會(huì)拋出一個(gè)ClassCastException異常台诗。
2.通過Class對象來獲取對象的類型完箩。如
Class c = Class.forName(“Apple”);
Object o = c.newInstance();
3.通過關(guān)鍵字instanceof或Class.isInstance()方法來確定對象是否屬于某個(gè)特定類型的實(shí)例,準(zhǔn)確的說拉队,應(yīng)該是instanceof / Class.isInstance()可以用來確定對象是否屬于某個(gè)特定類及其所有基類的實(shí)例弊知,這和equals() / ==不一樣,它們用來比較兩個(gè)對象是否屬于同一個(gè)類的實(shí)例粱快,沒有考慮繼承關(guān)系秩彤。
如果類型在編譯時(shí)已知,可以通過RTTI來獲取事哭。即在編譯時(shí)漫雷,編譯器必須知道所有通過RTTI來處理的類。但如果使用反射機(jī)制鳍咱,可以不受這個(gè)限制降盹,它主要應(yīng)用于兩種情況:
第一種情況,是“基于構(gòu)件的編程”這種編程方式中谤辜,將使用某種基于快速應(yīng)用開發(fā)(RAD)的應(yīng)用構(gòu)建工具來構(gòu)建項(xiàng)目蓄坏。這是現(xiàn)在最常見的可視化編程方法,通過代表不同組件的圖標(biāo)拖動(dòng)到圖板上丑念,然后設(shè)置”構(gòu)件“(組件)的屬性值來配置它們來創(chuàng)建程序涡戳。
要做到這種配置編程,就必須要求構(gòu)件都是可實(shí)例化的脯倚,并且要暴露其部分信息渔彰,使得程序員可以讀取和設(shè)置構(gòu)件的值和狀態(tài)。當(dāng)處理GUI時(shí)間的構(gòu)件時(shí)還必須暴露相關(guān)方法的事件處理細(xì)節(jié)推正,以便RAD環(huán)境幫助程序員覆蓋這些處理事件的方法胳岂。在這里,就要用到反射的機(jī)制來檢查可用的方法并返回方法實(shí)體對象舔稀。Java通過JavaBeans提供了基于構(gòu)件的編程架構(gòu)乳丰。
第二種情況,在運(yùn)行時(shí)獲取類的信息的另外一個(gè)動(dòng)機(jī)内贮,就是希望能夠提供在跨網(wǎng)絡(luò)的遠(yuǎn)程平臺(tái)上創(chuàng)建和運(yùn)行對象的能力产园。這被成為遠(yuǎn)程調(diào)用(RMI)汞斧,它允許一個(gè)Java程序?qū)ο蠓植皆诙嗯_(tái)機(jī)器上,這種分步能力將幫助開發(fā)人員執(zhí)行一些需要進(jìn)行大量計(jì)算的任務(wù)什燕,充分利用計(jì)算機(jī)資源粘勒,提高運(yùn)行速度。
Class類支持反射屎即,是在java.lang.reflect中包含了Field/Method/Constructor類庙睡,每個(gè)類都實(shí)現(xiàn)了Member接口。這些類型的對象都是由JVM在運(yùn)行時(shí)創(chuàng)建的技俐,用來表示未知類里對應(yīng)的成員乘陪。如可以用Constructor類創(chuàng)建新的對象,用get()和set()方法讀取和修改與Field對象關(guān)聯(lián)的字段雕擂,用invoke()方法調(diào)用與Method對象關(guān)聯(lián)的方法啡邑。
同時(shí),還可以調(diào)用getFields()井赌、getMethods()谤逼、getConstructors()等方法來返回表示字段、方法以及構(gòu)造器的對象數(shù)組仇穗。這樣流部,未知的對象的類信息在運(yùn)行時(shí)就能被完全確定下來,而在編譯時(shí)不需要知道任何信息纹坐。
另外贵涵,RTTI有時(shí)能解決效率問題。當(dāng)程序中使用多態(tài)給程序的運(yùn)行帶來負(fù)擔(dān)的時(shí)候恰画,可以使用RTTI編寫一段代碼來提高效率宾茂。
reflect的作用:
了解類的各種信息
操作成員變量
調(diào)用成員方法
創(chuàng)建對象實(shí)例(instance)
reflect操作實(shí)例:
//獲取類名的3種方法
(1) ? ?className = d.getClass().getName());
(2) ? ?String className = "reflect.Dog";
? ? ? ? Class c = Class.forName(className);
? ? ? ? className = c.getName() ;
(3) ? ?Class cc = Dog.class;
? ? ? ? ?className = cc.getName());
?//獲取類方法
(1)Class dogClass = Dog.class;
? ? Method[] m1 = dogClass.getMethods(); //打印公共方法
? ? for(Method me:m1){
? ? ? ? System.out.println(me.getName());
? ? }
(2)Method[] m2 = dogClass.getDeclaredMethods(); //打印自己定義的所有方法
? ? for(Method me:m2){
? ? ? ? ?System.out.println(me.getName());
? ? }
//獲取類實(shí)現(xiàn)的所有接口
ClassdogClass = Dog.class;
for(Class i:dogClass.getInterfaces()){
? ? System.out.println(i.getName());
}
//獲取類的所有構(gòu)造函數(shù)
Constructor[] getConstructor = Class.forName(d.getClass().getName()).getConstructors();
for(Constructor c:getConstructor){
? ? System.out.println(c);
}
//獲取類的成員屬性
Field []field = d.getClass().getDeclaredFields();
for(Field f:field){
? ? System.out.println(f.getName());
}
//獲取類的父類
Class c = d.getClass().getSuperclass();
System.out.println(c.getName());
//2種創(chuàng)建對象的實(shí)例的方法
Class dogClass = Dog.class;
1:不帶參數(shù)的構(gòu)造函數(shù)
? ? ? ? ?Object o1 = dogClass.newInstance();
? ? ? ? ?System.out.println(o1);
2:帶參數(shù)的構(gòu)造函數(shù)
? ? ? ? ?Constructor c = dogClass.getConstructor(new Class []{String.class});
? ? ? ? ?Dog o2 = (Dog)c.newInstance(new Object []{"xiaohuang"});
? ? ? ? ?System.out.println(o2.name);
//操作成員變量
ClassdogClass = Dog.class;
Field[] fields = dogClass.getDeclaredFields();
for(Field f:fields){ ? ? //遍歷打印所有成員變量
? ? System.out.println(f.getName());
}
//操作公有變量
Field f = dogClass.getField("name"); ??
f.set(o, "erhei"); ? //將對象o的name屬性值改為erhei
//操作私有變量
Field f2 = dogClass.getDeclaredField("owner");
f2.setAccessible(true); ? //獲取成員變量owner的訪問權(quán)限
f2.set(o, "john");
//調(diào)用成員方法
ClassdogClass = Dog.class;
Object o = dogClass.newInstance();
Method m = dogClass.getMethod("run", new Class[]{});
m.invoke(o, new Object[]{});
}