[JAVA學(xué)習(xí)筆記](méi) 反射機(jī)制
Java的反射通過(guò)Class類和java.lang.reflect類庫(kù)實(shí)現(xiàn)铐刘。通過(guò)它們歧杏,可以動(dòng)態(tài)獲得類的構(gòu)造器镰惦、方法、數(shù)據(jù)成員等信息犬绒,并創(chuàng)建新對(duì)象旺入、執(zhí)行方法和設(shè)置數(shù)據(jù)成員。
通過(guò)反射可以獲得類的所有構(gòu)造器凯力、方法和數(shù)據(jù)成員茵瘾,即便它們是被封裝在類內(nèi)部(private/protected/default)。因此咐鹤,使用反射需要考慮拗秘,對(duì)違反訪問(wèn)權(quán)限的操作是否有風(fēng)險(xiǎn)(如日后更新導(dǎo)致封裝改變)。
通過(guò)反射機(jī)制可以獲取以下相關(guān)內(nèi)容
- Class 對(duì)象
- 類名
- 修飾符
- 包信息
- 父類
- 實(shí)現(xiàn)的接口
- 構(gòu)造器
- 方法
- 變量
- 注解
獲取 Class 對(duì)象
Class.forName("org.test.Person"); //完整類名
String.class;
object.getClass();
Class 對(duì)象的幾個(gè)方法
getFields() / getDeclaredFields()
getFields() 獲得類的所有 public 數(shù)據(jù)成員慷暂,包括父類的聘殖;
getDeclaredFields() 獲得類的所有數(shù)據(jù)成員 (public, protected, private, default),不包括父類行瑞。
其他 getXxx() / getDeclaredXxx() 邏輯與此類似奸腺。newInstance()
創(chuàng)建實(shí)例,返回Object
類型血久。
通過(guò) Class 對(duì)象獲取實(shí)例
通過(guò)默認(rèn)構(gòu)造函數(shù)
Class c = ...;
Object obj = c.newInstance();
通過(guò)其他構(gòu)造函數(shù)
Class c = ...;
Constructor constructor = c.getConstructor(String.class,int.class);
Object obj = c.newInstance("abc", 123);
由此可知突照,Class.newInstance()
方法可以獲得類對(duì)象的實(shí)例,本質(zhì)是執(zhí)行了對(duì)應(yīng)的構(gòu)造函數(shù)氧吐,獲取 Object 對(duì)象之后讹蘑,就可以對(duì)其進(jìn)行強(qiáng)制轉(zhuǎn)換了。轉(zhuǎn)換成接口后還可以調(diào)用接口中的函數(shù)筑舅。
強(qiáng)制類型轉(zhuǎn)換
假定 Student 是 Person 的的子類
靜態(tài)強(qiáng)制類型轉(zhuǎn)換
Person person = new Student();
Student student = (Student)person;
動(dòng)態(tài)強(qiáng)制類型轉(zhuǎn)換
Person person = new Person();
Student student = Student.class.cast(person);
動(dòng)態(tài)強(qiáng)制轉(zhuǎn)換方法更靈活座慰,但應(yīng)用的場(chǎng)景并不多(Java SE5類庫(kù)中僅有一例)
變量
通過(guò)如下方式訪問(wèn)一個(gè)類的成員變量:
Field[] fields = c.getFields();
返回的Field對(duì)象數(shù)組包含了指定類中聲明為公有的(public)的所有變量集合。通過(guò) Field 對(duì)象翠拣,可以訪問(wèn)變量名稱版仔,變量類型,或是設(shè)置或者獲取變量的值误墓。
要想獲取私有變量蛮粮,可以調(diào)用Class.getDeclaredField(name)
方法或者Class.getDeclaredFields()
方法, 但若要讀取私有變量的值, 需要打開訪問(wèn): field.setAccessible(true);
獲得變量名字:
field.getName()
獲得變量值:
field.get(this);
設(shè)置變量值:
Field[] fields = this.getClass().getDeclaredFields();
for(Field field : fields){
field.setAccessible(true);
field.set(this, 123);
}
這里要注意的是被 set 的對(duì)象的類型要和其第二個(gè)參數(shù)的類型一致(可以強(qiáng)制轉(zhuǎn)換為相應(yīng)類型即可,比如123可以轉(zhuǎn)換為123.0谜慌,但是不能轉(zhuǎn)換為"123")
方法
Method[] methods = aClass.getMethods();
此處不作整理然想。