Android架構(gòu)師之路--Java進(jìn)階基礎(chǔ)--注解與反射

Java進(jìn)階基礎(chǔ)--注解與反射

一岗喉、注解

Java注解(Annotation)又稱Java標(biāo)注,是JDK5.0引入的一種注釋機(jī)制炸庞。注解是元數(shù)據(jù)的一種形式钱床,提供有關(guān)于程序但不屬于程序本身的數(shù)據(jù)。注解對(duì)它們注解的代碼的操作沒(méi)有直接影響埠居。

1查牌、注解聲明

Java中所有的注解,默認(rèn)實(shí)現(xiàn)Annotation接口:

package java.lang.annotation;

public interface Annotation {

????boolean equals(Object obj);

????int hashCode();

????String toString();

????Class<? extends Annotation> annotationType();

}

于聲明一個(gè)“Class”不同的是滥壕,注解的聲明使用@interface關(guān)鍵字纸颜。

public @interface Lance{ }

1.1、元注解

在定義注解時(shí)捏浊,注解類也能夠使用其他的注解聲明懂衩。對(duì)注解類型進(jìn)行注解的注解類,我們稱之為meta-annotation(元注解)金踪。一般的浊洞,我們?cè)诙x自定義注解時(shí),需要指定的元注解有兩個(gè):

@Target

注解標(biāo)記另一個(gè)注解胡岔,以限制可以應(yīng)用注解的Java元素類型法希。目標(biāo)注解指定以下元素類型之一作為其值:

①ElementType.ANNOTATION_TYPE? 可以應(yīng)用于注解類型。

②ElementType.CONSTRUCTOR 可以應(yīng)用于構(gòu)造函數(shù)靶瘸。

③ElementType.FIELD 可以應(yīng)用于字段或?qū)傩浴?/p>

④ElementType.LOCAL_VARIABLE 可以應(yīng)用于局部變量苫亦。

⑤ElementType.METHPD 可以應(yīng)用于方法級(jí)注解。

⑥ElementType.PACKAGE 可以應(yīng)用于包聲明怨咪。

⑦ElementType.PARAMETER 可以應(yīng)用于方法的參數(shù)屋剑。

⑧ElementType.TYPE 可以應(yīng)用于類的任何元素。

@Retention

注解指定標(biāo)記注解的存儲(chǔ)方式:

①RetentionPolicy.SOURCE 標(biāo)記的注解僅保留在源碼級(jí)別中诗眨,并被編譯器忽略唉匾。

②RetentionPolicy.CLASS 標(biāo)記的注解在編譯時(shí)由編譯器保留,但Java虛擬機(jī)(JVM)會(huì)忽略匠楚。

③RetentionPolicy.RUNTIME 標(biāo)記的注解由JVM保留巍膘,因此運(yùn)行時(shí)環(huán)境可以使用它。

另外還有@Documented 與 @Inherited 元注解芋簿,前者用于被javadoc工具提取成文檔峡懈,后者表示允許子類繼承父類中定義的注解。

@Retention 三個(gè)值中 SOURCE < CLASS < RUNTIME与斤,即CLASS包含了SOURCE肪康,RUNTIME包含SOURCE荚恶、CLASS。

例子:

@Target({ElementType.TYPE,ElementType.FIELD}) // 允許在類與類屬性上標(biāo)記該注解

@Retention(RetentionPolicy.SOURCE) //注解保留在源碼中

public @interface Lance {}

1.2梅鹦、注解類型元素

在聲明注解中裆甩,允許在使用注解時(shí)傳遞參數(shù)冗锁。

@Target({ElementType.TYPE,ElementType.FIELD})

@Retention(RetentionPolicy.SOURCE)

public @interface Lance {

????String value(); //無(wú)默認(rèn)值

????int age() default 1; //有默認(rèn)值

}

注意:在使用注解時(shí)齐唆,如果定義的注解中的類型元素?zé)o默認(rèn)值,則必須進(jìn)行傳值冻河。

1.3箍邮、注解應(yīng)用場(chǎng)景

按照@Retention元注解定義的注解存儲(chǔ)方式,注解可以被在三種場(chǎng)景中使用:

1.4叨叙、Android注解語(yǔ)法檢查

在Android中我們需要設(shè)計(jì)接口以供使用者調(diào)用時(shí)锭弊,如出現(xiàn)需要對(duì)入?yún)⑦M(jìn)行類型限定,如限定為資源ID擂错,布局ID等類型參數(shù)味滞,將參數(shù)類型直接給定int即可。然而钮呀,我們可以利用Android為我們提供的語(yǔ)法檢查注解剑鞍,來(lái)輔助進(jìn)行更為直接的參數(shù)類型檢查與提示。

參數(shù)限制為:圖片資源ID

public Drawable getDrawable(@Drawable int id) throw是 NotFoundException

同時(shí)爽醋,我們也可以使用@intDef來(lái)定義自己的入?yún)㈩愋蜋z查蚁署。

二、反射

一般情況下蚂四,我們使用某個(gè)類時(shí)必定知道它是什么類光戈,是用來(lái)做什么的,并且能都獲得此類的引用遂赠。于是我們直接對(duì)這個(gè)類進(jìn)行實(shí)例化久妆,之后使用這個(gè)類進(jìn)行操作。

反射則是一開(kāi)始并不知道我們初始化的類對(duì)象是什么跷睦,自然也無(wú)法使用new關(guān)鍵字來(lái)創(chuàng)建對(duì)象筷弦。這時(shí)候,我們使用JDK提供的反射API進(jìn)行反射調(diào)用送讲。

反射就是在運(yùn)行狀態(tài)中奸笤,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法哼鬓;對(duì)于任意一個(gè)對(duì)象监右,都能夠調(diào)用它的任意方法和屬性;并且能改變它的屬性异希。是Java被視為動(dòng)態(tài)語(yǔ)言的關(guān)鍵健盒。

Java反射機(jī)制主要提供了以下功能:

①在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象

②在運(yùn)行時(shí)獲取或者修改任意一個(gè)類所具有的成員變量和方法

③在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法和屬性

1、Class

反射始于Class,Class是一個(gè)類扣癣,封裝了當(dāng)前對(duì)象所對(duì)應(yīng)的類的信息惰帽。

1.1、獲得Class對(duì)象

①通過(guò)類名獲取? ?類名.class

②通過(guò)對(duì)象獲取? ? 對(duì)象名.getClass()

③通過(guò)全類名獲取? ? ?Class.forName(全類名)? ? classLoader.loadClass(全類名)

2父虑、判斷是否為某個(gè)類的實(shí)例

一般地该酗,我們用 instanceof 關(guān)鍵字來(lái)判斷是否為某個(gè)類的實(shí)例。同時(shí)我們也可以借助反射中 Class 對(duì)象的isInstance() 方法來(lái)判斷是否為某個(gè)類的實(shí)例士嚎,它是一個(gè) native 方法: public native boolean isInstance(Object obj);?

判斷是否為某個(gè)類的類型:??public boolean isAssignableFrom(Class<?> cls)

3呜魄、創(chuàng)建實(shí)例

①使用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í)例莱衩。

//獲取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");

4爵嗅、獲取構(gòu)造器信息

獲取構(gòu)造器的方法:

①Constructor getConstructor(Class[] params)? 獲得使用特殊的參數(shù)類型的public構(gòu)造函數(shù)(包括父類)

②Constructor[] getConstructors()? ?獲得類的所有公共構(gòu)造函數(shù)

③Constructor getDeclaredConstructor(Class[] params)? ?獲得使用特定參數(shù)類型的構(gòu)造函數(shù)(包括私有)

④Constructor[] getDeclaredConstructors()? ?獲得類的所有構(gòu)造函數(shù)(與接入級(jí)別無(wú)關(guān))

5、獲取類的成員變量(字段)信息

獲取字段信息的方法:

①Field? getField(String name)? ? 獲得命名的公共字段(public修飾)

②Field[]? getFields()? ?獲得類的所有公共字段(public修飾)

③Field? getDeclaredField(String name)? ?獲得類聲明的命名的字段(包括private修飾)

④Field[]? getDeclaredFields? ?獲得類聲明的所有字段(包括private修飾)

當(dāng)我們從類中獲取了一個(gè)方法后笨蚁,就可以用 invoke() 方法來(lái)調(diào)用這個(gè)方法睹晒。

public Object invoke(Object obj, Object... args);

6、利用反射創(chuàng)建數(shù)組

數(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);

7、反射獲取泛型真實(shí)類型

當(dāng)我們對(duì)一個(gè)泛型類進(jìn)行反射時(shí)勒极,需要得到泛型中的真實(shí)數(shù)據(jù)類型是掰,來(lái)完成如JSON反序列化的操作。此時(shí)需要通過(guò)Type體系來(lái)完成辱匿。Type接口包含了一個(gè)實(shí)現(xiàn)類(Class)和四個(gè)實(shí)現(xiàn)接口:

①TypeVariable? ? ? ? ? ? ? ? ?泛型類型變量键痛。可以獲得泛型上下限等信息

②ParameterizedType? ? ? ?具體的泛型類型匾七⌒醵蹋可以獲得元數(shù)據(jù)中泛型簽名類型(泛型真實(shí)類型)

③GenericArrayType? ? ? ? ?當(dāng)需要描述的類型是泛型類的數(shù)組時(shí),比如List[],Map[]昨忆,此接口會(huì)作為Type的實(shí)現(xiàn)

④WildcardType? ? ? ? ? ? ? ? 通配符泛型丁频。可以獲得上下限信息

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末邑贴,一起剝皮案震驚了整個(gè)濱河市席里,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拢驾,老刑警劉巖奖磁,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異繁疤,居然都是意外死亡咖为,警方通過(guò)查閱死者的電腦和手機(jī)秕狰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)躁染,“玉大人鸣哀,你說(shuō)我怎么就攤上這事⊥掏” “怎么了我衬?”我有些...
    開(kāi)封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)备畦。 經(jīng)常有香客問(wèn)我低飒,道長(zhǎng),這世上最難降的妖魔是什么懂盐? 我笑而不...
    開(kāi)封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮糕档,結(jié)果婚禮上莉恼,老公的妹妹穿的比我還像新娘。我一直安慰自己速那,他們只是感情好俐银,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著端仰,像睡著了一般捶惜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上荔烧,一...
    開(kāi)封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天吱七,我揣著相機(jī)與錄音,去河邊找鬼鹤竭。 笑死踊餐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的臀稚。 我是一名探鬼主播吝岭,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吧寺!你這毒婦竟也來(lái)了窜管?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤稚机,失蹤者是張志新(化名)和其女友劉穎幕帆,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體抒钱,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜓肆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年颜凯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仗扬。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡症概,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出早芭,到底是詐尸還是另有隱情彼城,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布退个,位于F島的核電站募壕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏语盈。R本人自食惡果不足惜舱馅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刀荒。 院中可真熱鬧代嗤,春花似錦、人聲如沸缠借。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)泼返。三九已至硝逢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绅喉,已是汗流浹背渠鸽。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留霹疫,地道東北人拱绑。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像丽蝎,于是被迫代替她去往敵國(guó)和親猎拨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354