日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

第三節(jié) 自定義Annotation

 KILLKISS 2013-08-25
第三節(jié) 自定義Annotation
使用過spring框架,ejb框架,cxf,junit2等支持Annotation技術(shù)的框架的人都會(huì)很清楚,其中除了jdk自帶的一些Annotation以外,我們還可以自己定義很多Annotation幫助我們進(jìn)行框架的搭建,這一小節(jié)我們將逐步的進(jìn)行自定義Annotation的說明。
Ok,開始我們的第一個(gè)Annotation程序之旅吧。
一:Quick Start
定義Annotation的時(shí)候和定義接口的方式很類似,只不過再interface前面加了@,我感覺在這一點(diǎn)sun公司確實(shí)有一些吝嗇,為何不開辟一個(gè)新的類型標(biāo)識(shí)符呢,呵呵,當(dāng)然這樣的抱怨也是無關(guān)緊要的,只要能達(dá)到目的即可。牢騷也不不多發(fā)了,直接上codes。
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. public @interface UserdefinedAnnotation {  
  4.       
  5. }  
代碼很簡(jiǎn)單,沒有任何的結(jié)構(gòu),只是一個(gè)空的Annotation,接下來演示一下如何對(duì)其進(jìn)行使用。
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. public class UseAnnotation {  
  4.       
  5.     @UserdefinedAnnotation  
  6.     public static void main(String[] args) {  
  7.         System.out.println("hello");  
  8.     }  
  9. }  
上述的代碼簡(jiǎn)單到再也不能簡(jiǎn)單,甚至簡(jiǎn)單到說明不了任何問題,只是從它上面可以看得出來我們?nèi)绾巫远ㄒ粋€(gè)Annotation,并且如何的使用它,我們并沒有給自定義Annotation中添加任何的屬性,甚至沒有指定其保持力(Retention),可繼承性(Inherited),標(biāo)注對(duì)象(Target)等,再接下來的描述中我們會(huì)逐步進(jìn)行說明。
二:Annotation屬性值
Annotation屬性值大致有以下三種:
● 基本類型
● 數(shù)組類型
● 枚舉類型
我們?cè)谙旅娴奈淖种袑?huì)一個(gè)個(gè)的進(jìn)行演示和說明。
1:基本串類型
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. public @interface UserdefinedAnnotation {  
  4.     int value();  
  5.     String name();  
  6.     String address();  
  7. }  
上面是一個(gè)自定義的annotation,可能稍微有一些復(fù)雜,只不過是為了更多的說明一下問題,可以看出來在定義屬性的時(shí)候有點(diǎn)像interface定義方法一樣,每一個(gè)屬性名稱之后需要加上括號(hào),接下來看看如何使用。
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2. public class UseAnnotation {  
  3.       
  4. @UserdefinedAnnotation(value=123,name="wangwenjun",address="火星")  
  5.     public static void main(String[] args) {  
  6.         System.out.println("hello");  
  7.     }  
  8. }  
如果在使用UserdefinedAnnotation時(shí)候不給相關(guān)的屬性賦值,會(huì)出現(xiàn)錯(cuò)誤。
需要說明的一點(diǎn)事如果一個(gè)annotation中只有一個(gè)屬性名字叫value,我沒在使用的時(shí)候可以給出屬性名也可以省略。
Java代碼  收藏代碼
  1. public @interface UserdefinedAnnotation {  
  2.     int value();  
  3. }  
  4. package com.wangwenjun.annatation.userdefined;  
  5.   
  6. public class UseAnnotation {  
  7.       
  8.     @UserdefinedAnnotation(value=123)  
  9.     public static void main(String[] args) {  
  10.         System.out.println("hello");  
  11.     }  
  12. }  
也可以寫成如下的形式
Java代碼  收藏代碼
  1. @UserdefinedAnnotation(123)  
  2.     public static void main(String[] args) {  
  3.         System.out.println("hello");  
  4. }  
直接對(duì)其進(jìn)行了省略。如果定義的屬性名字不叫value,那么屬性名字是不可以省略的哦!那是因?yàn)関alue屬性名是annotation默認(rèn)的一個(gè)屬性名,這一點(diǎn)很重要的哦,千萬不能忽略。
2:數(shù)組類型
我們?cè)谧远xannotation中定義一個(gè)數(shù)組類型的屬性,代碼如下:
Java代碼  收藏代碼
  1. public @interface UserdefinedAnnotation {  
  2.     int[] value();  
  3. }  
我們?nèi)绾问褂媚?,代碼如下:
Java代碼  收藏代碼
  1. public class UseAnnotation {  
  2.       
  3.     @UserdefinedAnnotation({123})  
  4.     public static void main(String[] args) {  
  5.         System.out.println("hello");  
  6.     }  
  7. }  
注意1:其中123外面的大括號(hào)是可以被省略的,因?yàn)橹挥幸粋€(gè)元素,如果里面有一個(gè)以上的元素的話,花括號(hào)是不能被省略的哦。比如{123,234}。
注意2:其中屬性名value我們?cè)谑褂玫臅r(shí)候進(jìn)行了省略,那是因?yàn)樗衯alue,如果是其他名字我們就不可以進(jìn)行省略了必須是@UserdefinedAnnotation(屬性名={123,234})這樣的格式。
3:枚舉類型
自從jdk5.0以后,java引進(jìn)了枚舉類型,我個(gè)人比較喜歡這樣的方式尤其在進(jìn)行業(yè)務(wù)邏輯判斷的if或者switch子句中使用很方便,而且還不容易出錯(cuò),大多時(shí)候都是作為一個(gè)函數(shù)的形式參數(shù)而存在,關(guān)于枚舉類型的使用請(qǐng)查看相應(yīng)的doc文檔。
我們定義一個(gè)enum類型
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. public enum DateEnum {  
  4.     Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday  
  5. }  
  6. 然后在定義一個(gè)annotation  
  7. package com.wangwenjun.annatation.userdefined;  
  8.   
  9. public @interface UserdefinedAnnotation {  
  10.     DateEnum week();  
  11. }  
可以看出annotation中的屬性類型為enum類型的,接下來我們看看他如何來使用
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. public class UseAnnotation {  
  4.       
  5.     @UserdefinedAnnotation(week=DateEnum.Sunday)  
  6.     public static void main(String[] args) {  
  7.         System.out.println("hello");  
  8.     }  
  9. }  
在使用上也是很方便的,直接用來進(jìn)行相關(guān)的引用,這樣再應(yīng)用的過程中就不會(huì)出現(xiàn)錯(cuò)誤。
4:默認(rèn)值
有時(shí)候我們?cè)谑褂胊nnotation的時(shí)候某一些屬性值是會(huì)被經(jīng)常使用到的,或者說他會(huì)有一個(gè)默認(rèn)值給我們直接進(jìn)行使用,那么我們?cè)诙xannotation的時(shí)候就可以為屬性直接給出默認(rèn)值,下面進(jìn)行一下簡(jiǎn)單的示例。
Java代碼  收藏代碼
  1. public @interface UserdefinedAnnotation {  
  2.     String name() default "zhangsan";  
  3. }  
在使用的時(shí)候我們可以不進(jìn)行指定
Java代碼  收藏代碼
  1. public class UseAnnotation {  
  2.       
  3.     @UserdefinedAnnotation()  
  4.     public static void main(String[] args) {  
  5.         System.out.println("hello");  
  6.     }  
  7. }  

當(dāng)然我們也可以自己對(duì)其進(jìn)行重新的設(shè)置,其中數(shù)組和枚舉類型的默認(rèn)值基本上類似,就不多做贅述了,自己進(jìn)行測(cè)試即可。
5:注意
● Annotation是不可以繼承其他接口的,這一點(diǎn)是需要進(jìn)行注意,這也是annotation的一個(gè)規(guī)定吧。
● Annotation也是存在包結(jié)構(gòu)的,在使用的時(shí)候直接進(jìn)行導(dǎo)入即可。
● Annotation類型的類型只支持原聲數(shù)據(jù)類型,枚舉類型和Class類型的一維數(shù)組,其他的類型或者用戶自定義的類都是不可以作為annotation的類型,我查看過文檔并且進(jìn)行過測(cè)試。
三:Retention標(biāo)記
Retention標(biāo)記是告知編譯器如何來處理我們自定義的annotation,指示注釋類型的注釋要保留多久。如果注釋類型聲明中不存在 Retention 注釋,則保留策略默認(rèn)為 RetentionPolicy.CLASS。
查看他的源代碼,會(huì)發(fā)現(xiàn)他有一個(gè)屬性value,類型為RetentionPolicy,RetentionPolicy是一個(gè)枚舉類型。其中有三個(gè)類型的值分別代表不同的意思。
CLASS 編譯器將把注釋記錄在類文件中,但在運(yùn)行時(shí) VM 不需要保留注釋。

RUNTIME 編譯器將把注釋記錄在類文件中,在運(yùn)行時(shí) VM 將保留注釋,因此可以反射性地讀取。
SOURCE 編譯器要丟棄的注釋

下面是一段簡(jiǎn)短的定義代碼示例。
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. import java.lang.annotation.Retention;  
  4. import java.lang.annotation.RetentionPolicy;  
  5.   
  6. @Retention(RetentionPolicy.RUNTIME)  
  7. public @interface UserdefinedAnnotation {  
  8.     String name() default "zhangsan";  
  9. }  
從上面的實(shí)例中我們自定義的annotation是一個(gè)runntime范圍的annotation,也就是說他會(huì)保持在源文件中并且也會(huì)在運(yùn)行時(shí)由JVM自動(dòng)調(diào)用。
我們先對(duì)它有一個(gè)感性的認(rèn)識(shí),知道有這么一個(gè)東西,在后面的文章中我會(huì)以一個(gè)示例對(duì)其進(jìn)行詳細(xì)的說明(會(huì)涉及到反射的相關(guān)東西)。其實(shí)Retention的名字翻譯過來就是“保持力”的意思,說明的很清楚,就是我的annotation存放在哪些地方,也就是說我的annotation他的影響力到底在哪。
四:AnnotatedElement
在jdk5.0以后java反射包增加了這樣一個(gè)接口,主要是用來對(duì)annotation進(jìn)行操作的,其中AccessibleObject, Class, Constructor, Field, Method, Package都對(duì)其進(jìn)行了實(shí)現(xiàn)繼承??偣灿幸韵滤膫€(gè)方法:
<T extends Annotation>
T
getAnnotation(Class<T> annotationType)
          如果存在該元素的指定類型的注釋,則返回這些注釋,否則返回 null。
Annotation[]
getAnnotations()
          返回此元素上存在的所有注釋。
Annotation[]
getDeclaredAnnotations()
          返回直接存在于此元素上的所有注釋。
boolean isAnnotationPresent(Class<? extends Annotation> annotationType)
          如果指定類型的注釋存在于此元素上,則返回 true,否則返回 false。
在接下來的章節(jié)中我們會(huì)進(jìn)行說明。
五:Target 標(biāo)記
在我們之前的實(shí)例中我們定義的annotation可以放在一個(gè)類的任何位置,那么我們是否可以對(duì)annotation的位置進(jìn)行設(shè)置呢,答案是可以的,這就是我們所要說的的Target 標(biāo)記,他里面也有一個(gè)枚舉類型的屬性value,其中枚舉類型為ElementType,有很多自定義的屬性,如下所示:

ANNOTATION_TYPE
          注釋類型聲明
CONSTRUCTOR
          構(gòu)造方法聲明
FIELD
          字段聲明(包括枚舉常量)
LOCAL_VARIABLE
          局部變量聲明
METHOD
          方法聲明
PACKAGE
          包聲明
PARAMETER
          參數(shù)聲明
TYPE
          類、接口(包括注釋類型)或枚舉聲明
上面的列表已經(jīng)講述的很清楚了,我們就不再進(jìn)行說明了,直接來一個(gè)小程序進(jìn)行演示吧,還是先來一個(gè)annotation,假設(shè)我們的annotation只能放在方法的前面
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Target;  
  5.   
  6. @Target(ElementType.METHOD)  
  7. public @interface UserdefinedAnnotation {  
  8.     String name() default "zhangsan";  
  9. }  
  10. package com.wangwenjun.annatation.userdefined;  
  11. public class UseAnnotation {  
  12.       
  13.     @UserdefinedAnnotation()  
  14.     public static void main(String[] args) {  
  15.         System.out.println("hello");  
  16.     }  
  17. }  
我們的annotation只能放在main方法上面放在其他的位置會(huì)出現(xiàn)錯(cuò)誤。
六:Documented 標(biāo)記
這個(gè)annotation非常簡(jiǎn)單,也非常容易理解,使用過javadoc命令的人都會(huì)很清楚,我們可以用javadoc命令將方法,類,變量等前面的注釋轉(zhuǎn)換成文檔,在默認(rèn)的情況下javadoc命令不會(huì)將我們的annotation生成再doc中去的,所以使用該標(biāo)記就是告訴jdk讓它也將annotation生成到doc中去,比如:
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Target;  
  6.   
  7. @Target(ElementType.METHOD)  
  8. @Documented  
  9. public @interface UserdefinedAnnotation {  
  10.     String name() default "zhangsan";  
  11. }  
七:Inherited標(biāo)記
該標(biāo)記的意思就是說,比如有一個(gè)類A,在他上面有一個(gè)標(biāo)記annotation,那么A的子類B是否不用再次標(biāo)記annotation就可以繼承得到呢?答案是肯定的,我們做一個(gè)簡(jiǎn)單的演示,首先我們有一個(gè)annotation
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Inherited;  
  6. import java.lang.annotation.Retention;  
  7. import java.lang.annotation.RetentionPolicy;  
  8. import java.lang.annotation.Target;  
  9.   
  10. @Documented  
  11. @Target(ElementType.TYPE)  
  12. @Retention(RetentionPolicy.RUNTIME)  
  13. @Inherited  
  14. public @interface UserdefinedAnnotation {  
  15.     String name() default "zhangsan";  
  16. }  
接著定義一個(gè)父類
package com.wangwenjun.annatation.userdefined;

@UserdefinedAnnotation
public class ParentClass {

}
父類什么都沒有干,只是一個(gè)空的類,并且有UserdefinedAnnotation的標(biāo)記,然后我們寫一個(gè)繼承他的子類。
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. public class ChildClass extends ParentClass{  
  4.       
  5. }  
我們準(zhǔn)備工作都已經(jīng)做完了,現(xiàn)在就是利用反射機(jī)制進(jìn)行一下簡(jiǎn)短的測(cè)試
Java代碼  收藏代碼
  1. package com.wangwenjun.annatation.userdefined;  
  2.   
  3. public class TestInherited {  
  4.     public static void main(String[] args) {  
  5.         Class<ChildClass> clazz = ChildClass.class;  
  6.         boolean isExist=clazz.isAnnotationPresent(UserdefinedAnnotation.class);  
  7.         if(isExist){  
  8.             System.out.println("子類繼承了父類的annotation");  
  9.         }else{  
  10.             System.out.println("子類沒有繼承父類的annotation");  
  11.         }  
  12.     }  
  13. }  
打印結(jié)果為:子類繼承了父類的annotation。可以看到子類果然繼承了父類的annotation標(biāo)記。 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多