您好,登錄后才能下訂單哦!
提起hook概念,相信大家都聽(tīng)說(shuō)過(guò),然后hook就是將反射和動(dòng)態(tài)代理運(yùn)用于Android平臺(tái)源碼之上的??墒?,反射的應(yīng)用場(chǎng)景缺非常廣泛,注解的內(nèi)容也同樣需要使用反射去獲取,所以反射是我們Android開(kāi)發(fā)者必須要學(xué)習(xí)的知識(shí)。
反射 (Reflection) 是 Java 的特征之一,它允許運(yùn)行中的 Java 程序獲取自身的信息,并且可以操作類或?qū)ο蟮膬?nèi)部屬性
簡(jiǎn)而言之,通過(guò)反射,我們可以在運(yùn)行時(shí)獲得程序或程序集中每一個(gè)類型的成員和成員的信息。程序中一般的對(duì)象的類型都是在編譯期就確定下來(lái)的,而 Java 反射機(jī)制可以動(dòng)態(tài)地創(chuàng)建對(duì)象并調(diào)用其屬性,這樣的對(duì)象的類型在編譯期是未知的。所以我們可以通過(guò)反射機(jī)制直接創(chuàng)建對(duì)象,即使這個(gè)對(duì)象的類型在編譯期是未知的。
反射的核心是 JVM 在運(yùn)行時(shí)才動(dòng)態(tài)加載類或調(diào)用方法/訪問(wèn)屬性,它不需要事先(寫(xiě)代碼的時(shí)候或編譯期)知道運(yùn)行對(duì)象是誰(shuí)。
Java 反射主要提供以下功能:
在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類;
在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象;
在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法(通過(guò)反射甚至可以調(diào)用private方法);
在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法
重點(diǎn):是運(yùn)行時(shí)而不是編譯時(shí)
使用 Class 類的 forName 靜態(tài)方法
public?static?Class<?>?forName(String?className)
直接獲取某一個(gè)對(duì)象的 class
Class<?>?klass?=?int.class;Class<?>?classInt?=?Integer.TYPE;
調(diào)用某個(gè)對(duì)象的 getClass() 方法
StringBuilder?str?=?new?StringBuilder("123"); Class<?>?klass?=?str.getClass();
一般地,我們用 instanceof 關(guān)鍵字來(lái)判斷是否為某個(gè)類的實(shí)例。同時(shí)我們也可以借助反射中 Class 對(duì)象的 isInstance() 方法來(lái)判斷是否為某個(gè)類的實(shí)例,它是一個(gè) native 方法:
public?native?boolean?isInstance(Object?obj);
通過(guò)反射來(lái)生成對(duì)象主要有兩種方式。
使用Class對(duì)象的newInstance()方法來(lái)創(chuàng)建Class對(duì)象對(duì)應(yīng)類的實(shí)例。
Class<?>?c?=?String.class;Object?str?=?c.newInstance();
先通過(guò)Class對(duì)象獲取指定的Constructor對(duì)象,再調(diào)用Constructor對(duì)象的newInstance()方法來(lái)創(chuàng)建實(shí)例。這種方法可以用指定的構(gòu)造器構(gòu)造類的實(shí)例。
//獲取String所對(duì)應(yīng)的Class對(duì)象Class<?>?c?=?String.class;//獲取String類帶一個(gè)String參數(shù)的構(gòu)造器Constructor?constructor?=?c.getConstructor(String.class); //根據(jù)構(gòu)造器創(chuàng)建實(shí)例 Object?obj?=?constructor.newInstance("23333"); System.out.println(obj);
得到構(gòu)造器的方法
Constructor?getConstructor(Class[]?params)?--?獲得使用特殊的參數(shù)類型的公共構(gòu)造函數(shù),? Constructor[]?getConstructors()?--?獲得類的所有公共構(gòu)造函數(shù)? Constructor?getDeclaredConstructor(Class[]?params)?--?獲得使用特定參數(shù)類型的構(gòu)造函數(shù)(與接入級(jí)別無(wú)關(guān))? Constructor[]?getDeclaredConstructors()?--?獲得類的所有構(gòu)造函數(shù)(與接入級(jí)別無(wú)關(guān))
獲取類構(gòu)造器的用法與上述獲取方法的用法類似。主要是通過(guò)Class類的getConstructor方法得到Constructor類的一個(gè)實(shí)例,而Constructor類有一個(gè)newInstance方法可以創(chuàng)建一個(gè)對(duì)象實(shí)例:
public?T?newInstance(Object?...?initargs)
獲得字段信息的方法
Field?getField(String?name)?--?獲得命名的公共字段? Field[]?getFields()?--?獲得類的所有公共字段? Field?getDeclaredField(String?name)?--?獲得類聲明的命名的字段? Field[]?getDeclaredFields()?--?獲得類聲明的所有字段
獲得方法信息的方法
--?使用特定的參數(shù)類型,獲得命名的公共方法Method?getMethod(String?name,?Class[]?params)--?獲得類的所有公共方法Method[]?getMethods()?? --?使用特寫(xiě)的參數(shù)類型,獲得類聲明的命名的方法? Method?getDeclaredMethod(String?name,?Class[]?params)? --?獲得類聲明的所有方法? Method[]?getDeclaredMethods()
當(dāng)我們從類中獲取了一個(gè)方法后,我們就可以用 invoke() 方法來(lái)調(diào)用這個(gè)方法。invoke 方法的原型為:
public?Object?invoke(Object?obj,?Object...?args) ????????throws?IllegalAccessException,?IllegalArgumentException, ???????????InvocationTargetException
數(shù)組在Java里是比較特殊的一種類型,它可以賦值給一個(gè)Object Reference
其中的Array類為java.lang.reflect.Array類。我們通過(guò)Array.newInstance()創(chuàng)建數(shù)組對(duì)象,它的原型是:
public?static?Object?newInstance(Class<?>?componentType,?int?length) ????????throws?NegativeArraySizeException?{????????return?newArray(componentType,?length); ????}
而 newArray 方法是一個(gè) native 方法,它在 HotSpot JVM 里的具體實(shí)現(xiàn)我們后邊再研究,這里先把源碼貼出來(lái):
private?static?native?Object?newArray(Class<?>?componentType,?int?length) ????????throws?NegativeArraySizeException;
反射會(huì)額外消耗一定的系統(tǒng)資源,因此如果不需要?jiǎng)討B(tài)地創(chuàng)建一個(gè)對(duì)象,那么就不需要用反射
反射調(diào)用方法時(shí)可以忽略權(quán)限檢查,因此可能會(huì)破壞封裝性而導(dǎo)致安全問(wèn)題
BAT主流Android架構(gòu)技術(shù)大綱+學(xué)習(xí)路線+全套視頻;
架構(gòu)技術(shù)詳解和學(xué)習(xí)路線與資料分享請(qǐng)看這篇;《BATJ一線大廠最主流的Android高級(jí)架構(gòu)技術(shù);體系詳解+學(xué)習(xí)路線》
(包括自定義控件、NDK、架構(gòu)設(shè)計(jì)、混合式開(kāi)發(fā)工程師(React native,Weex)、性能優(yōu)化、完整商業(yè)項(xiàng)目開(kāi)發(fā)等)
阿里P8級(jí)Android架構(gòu)師技術(shù)腦圖;
全套體系化高級(jí)架構(gòu)視頻;七大主流技術(shù)模塊,視頻+源碼+筆記
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。