- Spring快速入門(mén)
- 崔彥威 盧欣欣 王倩
- 1816字
- 2020-06-29 17:30:38
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:人
- Vue.js設(shè)計(jì)與實(shí)現(xiàn)
- JavaScript全程指南
- 算法零基礎(chǔ)一本通(Python版)
- C語(yǔ)言程序設(shè)計(jì)(第2版)
- 精通API架構(gòu):設(shè)計(jì)、運(yùn)維與演進(jìn)
- 你必須知道的204個(gè)Visual C++開(kāi)發(fā)問(wèn)題
- Visual Basic程序設(shè)計(jì)實(shí)驗(yàn)指導(dǎo)(第二版)
- Nagios Core Administration Cookbook(Second Edition)
- jQuery for Designers Beginner's Guide Second Edition
- C語(yǔ)言程序設(shè)計(jì)
- Python面試通關(guān)寶典
- Elasticsearch搜索引擎構(gòu)建入門(mén)與實(shí)戰(zhàn)
- Android開(kāi)發(fā)進(jìn)階實(shí)戰(zhàn):拓展與提升
- 亮劍C#項(xiàng)目開(kāi)發(fā)案例導(dǎo)航
- 谷歌JAX深度學(xué)習(xí)從零開(kāi)始學(xué)