反射:
其實(shí)就是動(dòng)態(tài)的從內(nèi)存加載一個(gè)指定的類,并獲取該類中的所有的內(nèi)容。
反射的好處:大大的增強(qiáng)了程序的擴(kuò)展性。
反射的基本步驟:
1. 獲得Class對(duì)象,就是獲取到指定的名稱的字節(jié)碼文件對(duì)象。
2. 實(shí)例化對(duì)象,獲得類的屬性、方法或構(gòu)造函數(shù)。
3. 訪問屬性、調(diào)用方法、調(diào)用構(gòu)造函數(shù)創(chuàng)建對(duì)象。
一: 獲取Class對(duì)象,有三種方式 :
1:通過每個(gè)對(duì)象都具備的方法getClass來獲取。弊端:必須要?jiǎng)?chuàng)建該類對(duì)象,才可以調(diào)用getClass方法。
2:每一個(gè)數(shù)據(jù)類型(基本數(shù)據(jù)類型和引用數(shù)據(jù)類型)都有一個(gè)靜態(tài)的屬性class。弊端:必須要先明確該類。
前兩種方式不利于程序的擴(kuò)展,因?yàn)槎夹枰诔绦蚴褂镁唧w的類來完成。
3:使用的Class類中的方法,靜態(tài)的forName方法。指定什么類名,就獲取什么類字節(jié)碼文件對(duì)象,這種方式的擴(kuò)展性最強(qiáng),只要將類名的字符串傳入即可。
1 Class clazz = Class.forName("com.makaruina.reflect.Person");
二: 獲取了字節(jié)碼文件對(duì)象后,然后就需要?jiǎng)?chuàng)建指定類的對(duì)象:
創(chuàng)建對(duì)象的兩種方式(其實(shí)就是對(duì)象在進(jìn)行實(shí)例化時(shí)的初始化方式):
1. 調(diào)用空參數(shù)的構(gòu)造函數(shù):
使用了Class類中的newInstance()方法。
2. 調(diào)用帶參數(shù)的構(gòu)造函數(shù):
先要獲取指定參數(shù)的構(gòu)造器對(duì)象,然后通過該構(gòu)造器對(duì)象的newInstance(實(shí)際參數(shù)) 進(jìn)行對(duì)象的初始化。
1 Class clazz = Class.forName("com.makaruina.reflect.Person");2 Constructor con = clazz.getConstructor(new Class[]{String.class,int.class});3 Person instance = (Person) con.newInstance("name",20);
綜上所述,第二種方式,必須要先明確具體的構(gòu)造函數(shù)的參數(shù)類型,不便于擴(kuò)展。所以一般情況下,被反射的類,內(nèi)部通常都會(huì)提供一個(gè)公有的空參數(shù)的構(gòu)造函數(shù)。
三:獲取類中的方法,屬性,構(gòu)造函數(shù)。
1. 獲取方法
1 //獲取類中所有的方法。 2 public static void method_1() throws Exception { 3 Class clazz = Class.forName("com.makaruina.reflect.Person"); 4 //獲取的是該類中所有的公有方法,包含繼承和實(shí)現(xiàn)的方法。 5 Method[] methods = clazz.getMethods(); 6 //獲取的是該類中的所有方法,包含私有方法,但不包含繼承的方法。 7 methods = clazz.getDeclaredMethods(); 8 for(Method method : methods) { 9 System.out.PRintln(method);10 }11 }12 //獲取指定方法;13 public static void method_2() throws Exception {14 Class clazz = Class.forName("com.makaruina.reflect.Person");15 //獲取指定名稱的方法。16 Method method = clazz.getMethod("show", int.class,String.class);17 //想要運(yùn)行指定方法,當(dāng)然是方法對(duì)象最清楚,為了讓方法運(yùn)行,調(diào)用方法對(duì)象的invoke方法即可,但是方法運(yùn)行必須要明確所屬的對(duì)象和具體的實(shí)際參數(shù)。18 Object obj = clazz.newInstance();19 method.invoke(obj, 39,"hehehe");//執(zhí)行一個(gè)方法20 }21 //想要運(yùn)行私有方法。22 public static void method_3() throws Exception {23 Class clazz = Class.forName("com.makaruina.reflect.Person");24 //想要獲取私有方法。必須用getDeclearMethod();25 Method method = clazz.getDeclaredMethod("method", null);26 // 私有方法不能直接訪問,因?yàn)闄?quán)限不夠。非要訪問,可以通過暴力的方式。27 method.setaccessible(true);//一般很少用,因?yàn)樗接芯褪请[藏起來,所以盡量不要訪問。28 }29 //反射靜態(tài)方法。30 public static void method_4() throws Exception {31 Class clazz = Class.forName("com.makaruina.reflect.Person");32 Method method = clazz.getMethod("function",null);33 method.invoke(null,null);34 }
2.獲取屬性
1 Field getField(String name) 2 返回一個(gè) Field 對(duì)象,它反映此 Class 對(duì)象所表示的類或接口的指定公共成員字段。 3 Field[] getFields() 4 返回一個(gè)包含某些 Field 對(duì)象的數(shù)組,這些對(duì)象反映此 Class 對(duì)象所表示的類或接口的所有可訪問公共字段。 5 Field getDeclaredField(String name) 6 返回一個(gè) Field 對(duì)象,該對(duì)象反映此 Class 對(duì)象所表示的類或接口的指定已聲明字段。 7 Field[] getDeclaredFields() 8 返回 Field 對(duì)象的一個(gè)數(shù)組,這些對(duì)象反映此 Class 對(duì)象所表示的類或接口所聲明的所有字段。
3.獲取構(gòu)造函數(shù)
1 Constructor<T> getConstructor(Class<?>... parameterTypes) 2 返回一個(gè) Constructor 對(duì)象,它反映此 Class對(duì)象所表示的類的指定公共構(gòu)造方法。3 Constructor<?>[] getConstructors() 4 返回一個(gè)包含某些 Constructor 對(duì)象的數(shù)組,這些對(duì)象反映此 Class 對(duì)象所表示的類的所有公共構(gòu)造方法。
好了,反射到這里就說完了,快餓死了。。。。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注