官术网_书友最值得收藏!

1.2 反射

本節(jié)首先介紹反射的基本概念,理解什么是反射,以及Class類和反射常用API,通過(guò)實(shí)例操作來(lái)學(xué)習(xí)反射的使用。

1.2.1 反射機(jī)制

在上面自定義注解時(shí)我們也有提到反射,要獲取類方法和字段的注解信息,必須通過(guò)Java的反射技術(shù)來(lái)獲取Annotation對(duì)象。那么什么是反射呢?在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性,這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為Java語(yǔ)言的反射機(jī)制。它有點(diǎn)類似照妖鏡的作用,不管是什么妖魔鬼怪(類或?qū)ο螅┒寄芸吹剿恼婷婺浚ǐ@取類的屬性方法、調(diào)用對(duì)象的屬性方法)。

1.2.2 理解Class類

反射機(jī)制可以動(dòng)態(tài)獲取類信息以及調(diào)用對(duì)象方法,那它是通過(guò)什么實(shí)現(xiàn)的呢?這就要介紹一下Class類了。首先明確Class也是一個(gè)類,只是它是一個(gè)描述類的類,也可以生成對(duì)象。對(duì)于每個(gè)類而言,在JRE中有且僅有一個(gè)不變的Class類型的對(duì)象,而這個(gè)Class類型的對(duì)象只能由系統(tǒng)建立,封裝了當(dāng)前對(duì)象所對(duì)應(yīng)的類的信息,有哪些屬性、方法、構(gòu)造器以及實(shí)現(xiàn)了哪些接口等。每個(gè)類的實(shí)例都會(huì)記得自己是由哪個(gè)Class實(shí)例所生成的。

要獲取類信息或調(diào)用對(duì)象方法,肯定首先要獲取到該類或?qū)ο髮?duì)應(yīng)的Class類的實(shí)例。一般獲取Class對(duì)象有3種方式。

● 通過(guò)類名獲取,類名.class。

● 通過(guò)對(duì)象獲取,對(duì)象.getClass()。

● 通過(guò)全類名獲取,Class.forName(全類名)。

這里我們可以使用字符串來(lái)做驗(yàn)證。

輸出結(jié)果:

     class java.lang.String
     class java.lang.String
     class java.lang.String

通過(guò)3種方式獲取到Class實(shí)例后,再了解一下Class類常用的方法(見(jiàn)表1-1)。

表1-1 Class類常用的方法

1.2.3 反射的使用

這里要著重介紹一下上面API的使用,因?yàn)樵诤竺嬉獙W(xué)習(xí)的Spring中IOC的原理就是反射加工廠模式。學(xué)好反射API有助于理解Spring框架內(nèi)部實(shí)現(xiàn)。為了演示Class方法的使用,在注解demo的基礎(chǔ)上對(duì)Person、Student類進(jìn)行了修改。

Person類:

Student類:

1.描述方法Method

描述方法主要是4個(gè)獲取方法(getMethods、getMethod、getDeclaredMethods、getDeclaredMethod)和1個(gè)調(diào)用方法(invoke)。

● getMethods:獲取clazz對(duì)應(yīng)類中的所有方法,不能獲取private方法,且獲取從父類繼承來(lái)的所有方法,包括私有父類的私有方法。

● getMethod:獲取clazz對(duì)應(yīng)類中指定方法名和參數(shù)類型的方法,不能獲取private方法,且獲取從父類繼承來(lái)的所有方法,包括私有父類的私有方法。因?yàn)榇嬖谕椒煌瑓?shù)這種情況,所以只有同時(shí)指定方法名和參數(shù)類型才能唯一確定一個(gè)方法。

● getDeclaredMethods:獲取所有方法,包括私有方法,所有聲明的方法,都可以獲取到,且只獲取當(dāng)前類的方法。

● getDeclaredMethod:獲取clazz對(duì)應(yīng)類中指定方法名和參數(shù)類型的方法,包括私有方法,所有聲明的方法,都可以獲取到,且只獲取當(dāng)前類的方法。

● invoke:執(zhí)行方法,第一個(gè)參數(shù)表示執(zhí)行哪個(gè)對(duì)象的方法,剩下的參數(shù)是執(zhí)行方法時(shí)需要傳入的參數(shù),私有方法的執(zhí)行必須在調(diào)用invoke之前加上一句“method.setAccessible(true);”。

輸出結(jié)果:

上面我們基本可以實(shí)現(xiàn)通過(guò)類名創(chuàng)建對(duì)象、通過(guò)方法名執(zhí)行方法。類名和方法名都是字符串,我們可以把它們放到一個(gè)配置文件中,根據(jù)配置文件來(lái)執(zhí)行方法,這樣就有點(diǎn)類似基于XML的Spring了。

2.描述字段Field

描述字段Field方法的使用和描述方法Method中方法的使用有點(diǎn)類似,也是4個(gè)獲取字段的方法(getFields、getField、getDeclaredFields、getDeclaredField)。

● getFields:獲得某個(gè)類的所有公共(public)字段,包括父類中的字段。

● getField:獲取某個(gè)類public成員變量中指定變量名的字段,包括基類。

● getDeclaredFields:獲得某個(gè)類所有聲明的字段,包括public、private和protected,但是不包括父類的聲明字段。

● getDeclaredField:獲取某個(gè)類的所有成員變量指定變量名的字段,不包括基類。

輸出結(jié)果:

     ---------getDeclaredFields---------
     StudentId
     ---------getFields---------
     StudentId
     ---------getDeclaredField---------
     StudentId
     ---------getField--------
     StudentId

上面通過(guò)反射獲取字段,得到字段之后就是獲取或設(shè)置字段的值了。如果字段是私有的,那么不管是讀值還是寫(xiě)值,都必須先調(diào)用setAccessible(true)方法,比如在Person類中,字段name字段是私有的。

               Class clazz = Class.forName("Reflection.Person");
               Person person = new Person("CYW");
       //獲取私有字段的值
               Field field = clazz.getDeclaredField("Name");
       //由于是私有字段,因此需要使用setAccessible(true)
       field.setAccessible(true);
               Object val = field.get(person);
               System.out.println(val);
       //改變私有字段的值
       field.set(person, "ivan");
               System.out.println(person.getName());

輸出結(jié)果:

     CYW
     ivan

3.描述構(gòu)造器Constructor

先介紹一下描述構(gòu)造函數(shù)Constructor用到的方法,主要還是4個(gè):getConstructors、getDeclaredConstructors、getConstructor、getDeclaredConstructor。和前面Method、Field用的方法進(jìn)行比較,舉一反三,我們也能大概了解這幾個(gè)方法的使用。其實(shí),在編程中有好多體現(xiàn)哲學(xué)思想的地方,有正有反,有陰有陽(yáng),學(xué)會(huì)思考,這樣可以以點(diǎn)帶面、觸類旁通。

● getConstructors:獲取對(duì)應(yīng)類中public類型的構(gòu)造函數(shù),且只獲取當(dāng)前類的構(gòu)造函數(shù)。

● getConstructor:獲取對(duì)應(yīng)類中public指定參數(shù)類型的構(gòu)造函數(shù),且只獲取當(dāng)前類的構(gòu)造函數(shù)。

● getDeclaredConstructors:獲取對(duì)應(yīng)類中所有構(gòu)造函數(shù),包括私有構(gòu)造函數(shù),且只獲取當(dāng)前類的構(gòu)造函數(shù)。

● getDeclaredConstructor:獲取對(duì)應(yīng)類中指定參數(shù)類型的方法,包括私有構(gòu)造函數(shù),且只獲取當(dāng)前類的方法。

輸出結(jié)果:

4.描述注解Annotation

描述注解主要用到getAnnotation(Class<A> annotationClass)方法,返回該元素指定類型的注解,否則返回null。

輸出結(jié)果:

     description:學(xué)生
     description:人
主站蜘蛛池模板: 城市| 乌审旗| 深圳市| 越西县| 平泉县| 二连浩特市| 陵川县| 平湖市| 洛宁县| 利津县| 东海县| 瓦房店市| 广昌县| 鲁山县| 宁蒗| 开阳县| 齐齐哈尔市| 洮南市| 嘉黎县| 固始县| 西乌珠穆沁旗| 宁阳县| 江孜县| 贞丰县| 遂平县| 闻喜县| 汶上县| 无极县| 武安市| 蓝山县| 左权县| 吴旗县| 西平县| 芮城县| 郴州市| 邓州市| 永年县| 承德市| 祁门县| 图片| 尚志市|