轉:http://blog.csdn.net/zen99t/article/details/49508447
(二)自定義注解
先上一段代碼有個大概的印象,再慢慢講解(其實代碼注釋已經講解地很清楚了):
- package diyDescription;
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Inherited;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Target({ElementType.METHOD,ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Inherited
- @Documented
- public @interface Description { //使用@interface關鍵字定義注解
- //成員以無參數無異常方式聲明
- String desc();
- /* String desc(int a);
- * String desc() throws Exception;
- * 都是錯誤的聲明方式
- */
- String author();
- // String author() default ”“; 合法的聲明
- //可以用default為成員指定一個默認值
- int age() default 18;
- /*
- * 如果聲明:Map map(); 則會報錯:
- * Invalid type Map for the annotation attribute Description.map;
- * only primitive type, String, Class, annotation, enumeration
- * are permitted or 1-dimensional arrays thereof
- *
- * 只有原始類型和String, Class, annotation, enumeration才可以
- */
- }
package diyDescription; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Description { //使用@interface關鍵字定義注解 //成員以無參數無異常方式聲明 String desc(); /* String desc(int a); * String desc() throws Exception; * 都是錯誤的聲明方式 */ String author(); // String author() default ""; 合法的聲明 //可以用default為成員指定一個默認值 int age() default 18; /* * 如果聲明:Map map(); 則會報錯: * Invalid type Map for the annotation attribute Description.map; * only primitive type, String, Class, annotation, enumeration * are permitted or 1-dimensional arrays thereof * * 只有原始類型和String, Class, annotation, enumeration才可以 */ }
首先看上面代碼的下面部分:

1.使用@interface關鍵字定義注解,注意關鍵字的位置
2.成員以無參數無異常的方式聲明,注意區別一般類成員變量的聲明
3.可以使用default為成員指定一個默認值,如上所示
4.成員類型是受限的,合法的類型包括原始類型以及String、Class、Annotation、Enumeration (JAVA的基本數據類型有8種:byte(字節)、short(短整型)、int(整數型)、long(長整型)、float(單精度浮點數類型)、double(雙精度浮點數類型)、char(字符類型)、boolean(布爾類型)
5.注解類可以沒有成員,沒有成員的注解稱為標識注解,例如JDK注解中的@Override、@Deprecation
6.如果注解只有一個成員,並且把成員取名為value(),則在使用時可以忽略成員名和賦值號“=” ,例如JDK注解的@SuppviseWarnings ;如果成員名不為value,則使用時需指明成員名和賦值號”=”,例子代碼如下:
- package jtzeng;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Target;
- @Target({ElementType.TYPE})
- public @interface SingleValue1 {
- String desc();
- }
- package jtzeng;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Target;
- @Target({ElementType.METHOD})
- public @interface SingleValue2 {
- String value();
- }
- package jtzeng;
- @SingleValue1( desc = “這是TYPE注解” ) //使用時需指明成員名和賦值號”=”
- public class Test {
- @SingleValue2(“這是METHOD注解”) //使用時可以忽略成員名和賦值號“=”
- public void print() {
- System.out.println();
- }
- }
package jtzeng; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target({ElementType.TYPE}) public @interface SingleValue1 { String desc(); } package jtzeng; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target({ElementType.METHOD}) public @interface SingleValue2 { String value(); } package jtzeng; @SingleValue1( desc = "這是TYPE注解" ) //使用時需指明成員名和賦值號"=" public class Test { @SingleValue2("這是METHOD注解") //使用時可以忽略成員名和賦值號“=” public void print() { System.out.println(); } }
2.元注解
何為元注解?就是注解的注解,就是給你自己定義的注解添加注解,你自己定義了一個注解,但你想要你的注解有什么樣的功能,此時就需要用元注解對你的注解進行說明了。
元注解有4個,如下代碼的上面部分:

2.1. @Target
即注解的作用域,用於說明注解的使用范圍(即注解可以用在什么地方,比如類的注解,方法注解,成員變量注解等等)
取值:
ElemenetType.CONSTRUCTOR—————————-構造器聲明
ElemenetType.FIELD ————————————–域聲明(包括 enum 實例)
ElemenetType.LOCAL_VARIABLE————————- 局部變量聲明
ElemenetType.METHOD ———————————-方法聲明
ElemenetType.PACKAGE ——————————— 包聲明
ElemenetType.PARAMETER ——————————參數聲明
ElemenetType.TYPE————————————— 類,接口(包括注解類型)或enum聲明
ElemenetType.FIELD ————————————–域聲明(包括 enum 實例)
ElemenetType.LOCAL_VARIABLE————————- 局部變量聲明
ElemenetType.METHOD ———————————-方法聲明
ElemenetType.PACKAGE ——————————— 包聲明
ElemenetType.PARAMETER ——————————參數聲明
ElemenetType.TYPE————————————— 類,接口(包括注解類型)或enum聲明
使用實例:
首先定義一個Description注解,
- package jtzeng;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Target;
- @Target({ElementType.TYPE,ElementType.FIELD})
- public @interface Description {
- String desc();
- String author();
- int age() default 21;
- }
package jtzeng; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target({ElementType.TYPE,ElementType.FIELD}) public @interface Description { String desc(); String author(); int age() default 21; }
然后再定義一個Test類進行測試,為了能讓大家看出錯誤,此處用圖片給出。
可以發現,因為上面定義注解時候,@Target只包含了
ElemenetType.TYPE和
ElemenetType.FIELD,所以在類和聲明中注解是可以的,而在方法上注解會報錯。

2.2. @Retention
描述的注解在什么范圍內有效。
取值有:
RetentionPolicy.SOURCE————————–只在源碼顯示,編譯時會丟失
RetentionPolicy.CLASS—————————–編譯時會記錄到class中,運行時忽略
RetentionPolicy.RUNTIME————————- 運行時存在,可以通過反射讀取
RetentionPolicy.CLASS—————————–編譯時會記錄到class中,運行時忽略
RetentionPolicy.RUNTIME————————- 運行時存在,可以通過反射讀取
使用實例:
下面給出的是簡單的定義,至於會有什么不同的效果,往后的
解析注解部分會講解。
- package jtzeng;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- @Retention(RetentionPolicy.RUNTIME) //運行時存在,可以通過反射讀取
- //@Retention(RetentionPolicy.SOURCE) //只在源碼顯示,編譯時會丟失
- //@Retention(RetentionPolicy.CLASS) //編譯時會記錄到class中,運行時忽略
- public @interface Description {
- String desc();
- String author() default “JTZeng”;
- int age() default 21;
- }
package jtzeng; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) //運行時存在,可以通過反射讀取 //@Retention(RetentionPolicy.SOURCE) //只在源碼顯示,編譯時會丟失 //@Retention(RetentionPolicy.CLASS) //編譯時會記錄到class中,運行時忽略 public @interface Description { String desc(); String author() default "JTZeng"; int age() default 21; }
2.3. @Inherited
1. 是一個標記注解,沒有成員,表示允許子類繼承該注解,也就是說如果一個使用了@Inherited修飾的注解被用於一個class時,則這個注解將被該class的子類繼承擁有
2. 使用了@Inherited修飾的注解只能被子類所繼承,並不可以從它所實現的接口繼承
3. 子類繼承父類的注解時,並不能從它所重載的方法繼承注解
使用實例:
- package jtzeng;
- import java.lang.annotation.Inherited;
- @Inherited
- public @interface Description {
- String desc();
- String author() default “JTZeng”;
- int age() default 21;
- }
package jtzeng; import java.lang.annotation.Inherited; @Inherited public @interface Description { String desc(); String author() default "JTZeng"; int age() default 21; }
2.4. @Documented
@Documented是一個標記注解,沒有成員。用於描述其它類型的annotation應該被作為被標注的程序成員的公共API,因此可以被例如javadoc此類的工具文檔化。(有點抽象,看例子吧)
使用實例:
- /*
- * 測試@Documented的功能
- */
- package jtzeng;
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Inherited;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Target({ElementType.METHOD,ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Inherited
- @Documented
- public @interface Description {
- String desc();
- String author() default “JTZeng”;
- int age() default 21;
- }
- /*
- * 定義一個Test測試類,類和方法都有注解
- */
- package jtzeng;
- @Description(desc=“這是TYPE注解”,author=“JTZeng”,age=21)
- public class Test {
- private String field = “自定義注解”;
- @Description(desc=“這是METHOD注解”,author=“JTZeng”,age=21)
- public void print() {
- System.out.println(field);
- }
- }
/* * 測試@Documented的功能 */ package jtzeng; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Description { String desc(); String author() default "JTZeng"; int age() default 21; } /* * 定義一個Test測試類,類和方法都有注解 */ package jtzeng; @Description(desc="這是TYPE注解",author="JTZeng",age=21) public class Test { private String field = "自定義注解"; @Description(desc="這是METHOD注解",author="JTZeng",age=21) public void print() { System.out.println(field); } }
然后,在Eclipse中,右鍵項目名稱,選擇Export,選擇Java——>javadoc,下一步,完成。看結果,左邊是添加了@Documented的效果,右邊是沒有添加的效果。


自定義注解結束~~