java 自定義註解

java自定義註解

Java註解是附加在代碼中的一些元信息,用於一些工具在編譯、運行時進行解析和使用,起到說明、配置的功能。
註解不會也不能影響代碼的實際邏輯,僅僅起到輔助性的做用。包含在 java.lang.annotation 包中。 html

一、元註解 java

元註解是指註解的註解。包括 @Retention @Target @Document @Inherited四種。 程序員


1.一、@Retention: 定義註解的保留策略 spring

@Retention(RetentionPolicy. SOURCE) //註解僅存在於源碼中,在class字節碼文件中不包含
@Retention(RetentionPolicy. CLASS) // 默認的保留策略,註解會在class字節碼文件中存在,但運行時沒法得到,
@Retention(RetentionPolicy.RUNTIME) // 註解會在class字節碼文件中存在,在運行時能夠經過反射獲取到
1.二、@Target:定義註解的做用目標
其定義的源碼爲:
複製代碼
1 @Documented 2 @Retention(RetentionPolicy.RUNTIME) 3 @Target(ElementType.ANNOTATION_TYPE) 4 public @interface Target { 5  ElementType[] value(); 6 }
複製代碼

@Target(ElementType.TYPE) //接口、類、枚舉、註解 數組

@Target(ElementType.FIELD) // 字段、枚舉的常量
@Target(ElementType.METHOD) // 方法
@Target(ElementType.PARAMETER) // 方法參數
@Target(ElementType.CONSTRUCTOR) // 構造函數
@Target(ElementType.LOCAL_VARIABLE) // 局部變量
@Target(ElementType.ANNOTATION_TYPE) // 註解
@Target(ElementType.PACKAGE) / //
由以上的源碼能夠知道,他的elementType 能夠有多個,一個註解能夠爲類的,方法的,字段的等等
1.三、@Document:說明該註解將被包含在javadoc中
1.四、@Inherited:說明子類能夠繼承父類中的該註解
二、java 註解的自定義
下面是自定義註解的一個例子
複製代碼
@Documented @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Yts {  public enum YtsType{util,entity,service,model};  public YtsType classType() default YtsType.util; } 
複製代碼
複製代碼
1 @Documented 2 @Retention(RetentionPolicy.RUNTIME) 3 @Target(ElementType.METHOD) 4 @Inherited 5 public @interface HelloWorld { 6 public String name()default ""; 7 }
複製代碼

@Retention(RetentionPolicy.RUNTIME) app

定義的這個註解是註解會在class字節碼文件中存在,在運行時能夠經過反射獲取到。 ide

@Target({ElementType.TYPE,ElementType.METHOD}) 函數

所以這個註解能夠是類註解,也能夠是方法的註解 工具

這樣一個註解就自定義好了,固然註解裏面的成員能夠爲基本的數據類型,也能夠爲數據,Object等等 學習

3 註解是定義好了,那麼怎麼來獲得,解析註解呢?

java的反射機制能夠幫助,獲得註解,代碼以下:

複製代碼
 1 public class ParseAnnotation {  2  3 public void parseMethod(Class clazz) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException{  4 Object obj = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});  5 for(Method method : clazz.getDeclaredMethods()){  6 HelloWorld say = method.getAnnotation(HelloWorld.class);  7 String name = "";  8 if(say != null){  9 name = say.name(); 10  method.invoke(obj, name); 11  } 12 Yts yts = (Yts)method.getAnnotation(Yts.class); 13 if(yts != null){ 14 if(YtsType.util.equals(yts.classType())){ 15 System.out.println("this is a util method"); 16 }else{ 17 System.out.println("this is a other method"); 18  } 19  } 20  } 21  } 22 @SuppressWarnings("unchecked") 23 public void parseType(Class clazz) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{ 24 Yts yts = (Yts) clazz.getAnnotation(Yts.class); 25 if(yts != null){ 26 if(YtsType.util.equals(yts.classType())){ 27 System.out.println("this is a util class"); 28 }else{ 29 System.out.println("this is a other class"); 30  } 31  } 32  } 33 34 }
複製代碼
前一個方法是解析獲得方法註解的,後一個方法是獲得類註解的

如下是測試方法類

複製代碼
 1 @Yts(classType =YtsType.util)  2 public class SayHell {  3  4 @HelloWorld(name = " 小明 ")  5  @Yts  6 public void sayHello(String name){  7 if(name == null || name.equals("")){  8 System.out.println("hello world!");  9 }else{ 10 System.out.println(name + "say hello world!"); 11  } 12  } 13 }
複製代碼
複製代碼
1 public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException { 2 ParseAnnotation parse = new ParseAnnotation(); 3 parse.parseMethod(SayHell.class); 4 parse.parseType(SayHell.class); 5 }
複製代碼

http://blog.csdn.net/yixiaogang109/article/details/7328466

一、Annotation的工做原理:

JDK5.0中提供了註解的功能,容許開發者定義和使用本身的註解類型。該功能由一個定義註解類型的語法和描述一個註解聲明的語法,讀取註解的API,一個使用註解修飾的class文件和一個註解處理工具組成。

Annotation並不直接影響代碼的語義,可是他能夠被看作是程序的工具或者類庫。它會反過來對正在運行的程序語義有所影響。

Annotation能夠衝源文件、class文件或者在運行時經過反射機制多種方式被讀取。

二、@Override註解:
java.lang
註釋類型 Override
@Target(value=METHOD)
@Retention(value=SOURCE)
public @interface Override

表示一個方法聲明打算重寫超類中的另外一個方法聲明。若是方法利用此註釋類型進行註解但沒有重寫超類方法,則編譯器會生成一條錯誤消息。

@Override註解表示子類要重寫父類的對應方法。

Override是一個Marker annotation,用於標識的Annotation,Annotation名稱自己表示了要給工具程序的信息。

下面是一個使用@Override註解的例子:

class A { private String id;
    A(String id){ this.id = id;
    } @Override public String toString() { return id;
    }
}
三、@Deprecated註解:
java.lang
註釋類型 Deprecated
@Documented
@Retention(value=RUNTIME)
public @interface Deprecated

用 @Deprecated 註釋的程序元素,不鼓勵程序員使用這樣的元素,一般是由於它很危險或存在更好的選擇。在使用不被同意的程序元素或在不被同意的代碼中執行重寫時,編譯器會發出警告。

@Deprecated註解表示方法是不被建議使用的。

Deprecated是一個Marker annotation。

下面是一個使用@Deprecated註解的例子:

class A { private String id;
    A(String id){ this.id = id;
    } @Deprecated public void execute(){
        System.out.println(id);
    } public static void main(String[] args) {
        A a = new A("a123");
        a.execute();
    }
}
四、@SuppressWarnings註解:
java.lang
註釋類型 SuppressWarnings
@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(value=SOURCE)
public @interface SuppressWarnings

指示應該在註釋元素(以及包含在該註釋元素中的全部程序元素)中取消顯示指定的編譯器警告。注意,在給定元素中取消顯示的警告集是全部包含元素中取消顯示的警告的超集。例如,若是註釋一個類來取消顯示某個警告,同時註釋一個方法來取消顯示另外一個警告,那麼將在此方法中同時取消顯示這兩個警告。

根據風格不一樣,程序員應該始終在最裏層的嵌套元素上使用此註釋,在那裏使用纔有效。若是要在特定的方法中取消顯示某個警告,則應該註釋該方法而不是註釋它的類。

@SuppressWarnings註解表示抑制警告。

下面是一個使用@SuppressWarnings註解的例子:

@SuppressWarnings("unchecked") public static void main(String[] args) {
    List list = new ArrayList();
    list.add("abc");
}
五、自定義註解:

使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation接口,由編譯程序自動完成其餘細節。在定義註解時,不能繼承其餘的註解或接口。

自定義最簡單的註解:

public @interface MyAnnotation {

}

使用自定義註解:

public class AnnotationTest2 { @MyAnnotation public void execute(){
        System.out.println("method");
    }
}
5.一、添加變量:
public @interface MyAnnotation {

    String value1();
}

使用自定義註解:

public class AnnotationTest2 { @MyAnnotation(value1="abc") public void execute(){
        System.out.println("method");
    }
}

當註解中使用的屬性名爲value時,對其賦值時能夠不指定屬性的名稱而直接寫上屬性值接口;除了value意外的變量名都須要使用name=value的方式賦值。

5.二、添加默認值:
public @interface MyAnnotation {

    String value1() default "abc";
}
5.三、多變量使用枚舉:
public @interface MyAnnotation {

    String value1() default "abc";
    MyEnum value2() default MyEnum.Sunny;
}
enum MyEnum{
    Sunny,Rainy
}

使用自定義註解:

public class AnnotationTest2 { @MyAnnotation(value1="a", value2=MyEnum.Sunny) public void execute(){
        System.out.println("method");
    }
}
5.四、數組變量:
public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定義註解:

public class AnnotationTest2 { @MyAnnotation(value1={"a","b"}) public void execute(){
        System.out.println("method");
    }
}
六、設置註解的做用範圍:
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Retention

指示註釋類型的註釋要保留多久。若是註釋類型聲明中不存在 Retention 註釋,則保留策略默認爲 RetentionPolicy.CLASS。

只有元註釋類型直接用於註釋時,Target 元註釋纔有效。若是元註釋類型用做另外一種註釋類型的成員,則無效。

public enum RetentionPolicy extends Enum<RetentionPolicy>

註釋保留策略。此枚舉類型的常量描述保留註釋的不一樣策略。它們與 Retention 元註釋類型一塊兒使用,以指定保留多長的註釋。

CLASS 編譯器將把註釋記錄在類文件中,但在運行時 VM 不須要保留註釋。 RUNTIME 編譯器將把註釋記錄在類文件中,在運行時 VM 將保留註釋,所以能夠反射性地讀取。 SOURCE 編譯器要丟棄的註釋。

@Retention註解能夠在定義註解時爲編譯程序提供註解的保留策略。

屬於CLASS保留策略的註解有@SuppressWarnings,該註解信息不會存儲於.class文件。

6.一、在自定義註解中的使用例子:
@Retention(RetentionPolicy.CLASS) public @interface MyAnnotation {

    String[] value1() default "abc";
}
七、使用反射讀取RUNTIME保留策略的Annotation信息的例子:
java.lang.reflect
        接口 AnnotatedElement 全部已知實現類:
        AccessibleObject, Class, Constructor, Field, Method, Package

表示目前正在此 VM 中運行的程序的一個已註釋元素。該接口容許反射性地讀取註釋。由此接口中的方法返回的全部註釋都是不可變而且可序列化的。調用者能夠修改已賦值數組枚舉成員的訪問器返回的數組;這不會對其餘調用者返回的數組產生任何影響。

若是此接口中的方法返回的註釋(直接或間接地)包含一個已賦值的 Class 成員,該成員引用了一個在此 VM 中不可訪問的類,則試圖經過在返回的註釋上調用相關的類返回的方法來讀取該類,將致使一個 TypeNotPresentException。

isAnnotationPresent
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

若是指定類型的註釋存在於此元素上,則返回 true,不然返回 false。此方法主要是爲了便於訪問標記註釋而設計的。

參數:

annotationClass - 對應於註釋類型的 Class 對象

返回:

若是指定註釋類型的註釋存在於此對象上,則返回 true,不然返回 false

拋出:

NullPointerException - 若是給定的註釋類爲 null

從如下版本開始:

1.5

getAnnotation
<T extends Annotation> T getAnnotation(Class<T> annotationClass)

若是存在該元素的指定類型的註釋,則返回這些註釋,不然返回 null。

參數:

annotationClass - 對應於註釋類型的 Class 對象

返回:

若是該元素的指定註釋類型的註釋存在於此對象上,則返回這些註釋,不然返回 null

拋出:

NullPointerException - 若是給定的註釋類爲 null

從如下版本開始:

1.5

getAnnotations
Annotation[] getAnnotations()

返回此元素上存在的全部註釋。(若是此元素沒有註釋,則返回長度爲零的數組。)該方法的調用者能夠隨意修改返回的數組;這不會對其餘調用者返回的數組產生任何影響。

返回:

此元素上存在的全部註釋

從如下版本開始:

1.5

getDeclaredAnnotations
Annotation[] getDeclaredAnnotations()

返回直接存在於此元素上的全部註釋。與此接口中的其餘方法不一樣,該方法將忽略繼承的註釋。(若是沒有註釋直接存在於此元素上,則返回長度爲零的一個數組。)該方法的調用者能夠隨意修改返回的數組;這不會對其餘調用者返回的數組產生任何影響。

返回:

直接存在於此元素上的全部註釋

從如下版本開始:

1.5


下面是使用反射讀取RUNTIME保留策略的Annotation信息的例子:

自定義註解:

@Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定義註解:

public class AnnotationTest2 { @MyAnnotation(value1={"a","b"}) @Deprecated public void execute(){
        System.out.println("method");
    }
}

讀取註解中的信息:

public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    AnnotationTest2 annotationTest2 = new AnnotationTest2(); //獲取AnnotationTest2的Class實例 Class<AnnotationTest2> c = AnnotationTest2.class; //獲取須要處理的方法Method實例 Method method = c.getMethod("execute", new Class[]{}); //判斷該方法是否包含MyAnnotation註解 if(method.isAnnotationPresent(MyAnnotation.class)){ //獲取該方法的MyAnnotation註解實例 MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); //執行該方法 method.invoke(annotationTest2, new Object[]{}); //獲取myAnnotation String[] value1 = myAnnotation.value1();
        System.out.println(value1[0]);
    } //獲取方法上的全部註解 Annotation[] annotations = method.getAnnotations(); for(Annotation annotation : annotations){
        System.out.println(annotation);
    }
}
八、限定註解的使用:

限定註解使用@Target。

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Target

指示註釋類型所適用的程序元素的種類。若是註釋類型聲明中不存在 Target 元註釋,則聲明的類型能夠用在任一程序元素上。若是存在這樣的元註釋,則編譯器強制實施指定的使用限制。 例如,此元註釋指示該聲明類型是其自身,即元註釋類型。它只能用在註釋類型聲明上:

@Target(ElementType.ANNOTATION_TYPE) public @interface MetaAnnotationType {
        ...
    }

此元註釋指示該聲明類型只可做爲複雜註釋類型聲明中的成員類型使用。它不能直接用於註釋:

@Target({})  public @interface MemberType {
        ...
    }

這是一個編譯時錯誤,它代表一個 ElementType 常量在 Target 註釋中出現了不僅一次。例如,如下元註釋是非法的:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD}) public @interface Bogus {
        ...
    }
public enum ElementType extends Enum<ElementType>

程序元素類型。此枚舉類型的常量提供了 Java 程序中聲明的元素的簡單分類。

這些常量與 Target 元註釋類型一塊兒使用,以指定在什麼狀況下使用註釋類型是合法的。

ANNOTATION_TYPE 註釋類型聲明 CONSTRUCTOR 構造方法聲明 FIELD 字段聲明(包括枚舉常量) LOCAL_VARIABLE 局部變量聲明 METHOD 方法聲明 PACKAGE 包聲明 PARAMETER 參數聲明 TYPE 類、接口(包括註釋類型)或枚舉聲明


註解的使用限定的例子:

@Target(ElementType.METHOD) public @interface MyAnnotation {

    String[] value1() default "abc";
}
九、在幫助文檔中加入註解:

要想在製做JavaDoc文件的同時將註解信息加入到API文件中,可使用java.lang.annotation.Documented。

在自定義註解中聲明構建註解文檔:

@Documented public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定義註解:

public class AnnotationTest2 { @MyAnnotation(value1={"a","b"}) public void execute(){
        System.out.println("method");
    }
}
十、在註解中使用繼承:

默認狀況下註解並不會被繼承到子類中,能夠在自定義註解時加上java.lang.annotation.Inherited註解聲明使用繼承。

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Inherited

指示註釋類型被自動繼承。若是在註釋類型聲明中存在 Inherited 元註釋,而且用戶在某一類聲明中查詢該註釋類型,同時該類聲明中沒有此類型的註釋,則將在該類的超類中自動查詢該註釋類型。此過程會重複進行,直到找到此類型的註釋或到達了該類層次結構的頂層 (Object) 爲止。若是沒有超類具備該類型的註釋,則查詢將指示當前類沒有這樣的註釋。

注意,若是使用註釋類型註釋類之外的任何事物,此元註釋類型都是無效的。還要注意,此元註釋僅促成從超類繼承註釋;對已實現接口的註釋無效。

 

Annotation在java的世界正鋪天蓋地展開,有空寫這一篇簡單的annotations的文章,算是關於Annotation入門的文章吧,但願能各位們能拋磚,共同窗習......
不講廢話了,實踐纔是硬道理.

第一部分:瞭解一下java1.5起默認的三個annotation類型:
一個是@Override:只能用在方法之上的,用來告訴別人這一個方法是改寫父類的。
一個是@Deprecated:建議別人不要使用舊的API的時候用的,編譯的時候會用產生警告信息,能夠設定在程序裏的全部的元素上.
一個是@SuppressWarnings:這一個類型能夠來暫時把一些警告信息消息關閉.
若是不清楚上面三個類型的具體用法,各位能夠baidu或google一下的,很簡單的。

第二部分:講一下annotation的概念先,再來說一下怎樣設計本身的annotation.
首先在jdk自帶的java.lang.annotation包裏,打開以下幾個源文件:

一、源文件Target.java

Java代碼 複製代碼
  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target (ElementType.ANNOTATION_TYPE)
  4. public @interface Target {
  5. ElementType[] value();
  6. }
  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target (ElementType.ANNOTATION_TYPE)
  4. public @interface Target {
  5. ElementType[] value();
  6. }
@Documented
   @Retention(RetentionPolicy.RUNTIME)
   @Target(ElementType.ANNOTATION_TYPE)
   public @interface Target {
      ElementType[] value();
   }



其中的@interface是一個關鍵字,在設計annotations的時候必須把一個類型定義爲@interface ,而不能用class或interface關鍵字(會不會以爲sun有點吝嗇,恰恰搞得與interface這麼像).

二、源文件Retention.java

Java代碼 複製代碼
  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target (ElementType.ANNOTATION_TYPE)
  4. public @interface Retention {
  5. RetentionPolicy value();
  6. }
  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target (ElementType.ANNOTATION_TYPE)
  4. public @interface Retention {
  5. RetentionPolicy value();
  6. }
@Documented
   @Retention(RetentionPolicy.RUNTIME)
   @Target(ElementType.ANNOTATION_TYPE)
   public @interface Retention {
      RetentionPolicy value();
   }



看到這裏,你們可能都模糊了,都不知道在說什麼,別急,往下看一下.
在上面的文件都用到了RetentionPolicy,ElementType這兩個字段,你可能就會猜到這是兩個java文件.的確,這兩個文件的源代碼以下:

三、源文件RetentionPolicy.java

Java代碼 複製代碼
  1. public enum RetentionPolicy {
  2. SOURCE,
  3. CLASS,
  4. RUNTIME
  5. }
  1. public enum RetentionPolicy {
  2. SOURCE,
  3. CLASS,
  4. RUNTIME
  5. }
public enum RetentionPolicy {
     SOURCE,
     CLASS,
     RUNTIME
    }


這是一個enum類型,共有三個值,分別是SOURCE,CLASS 和 RUNTIME.
SOURCE表明的是這個Annotation類型的信息只會保留在程序源碼裏,源碼若是通過了編譯以後,Annotation的數據就會消失,並不會保留在編譯好的.class文件裏面。
ClASS的意思是這個Annotation類型的信息保留在程序源碼裏,同時也會保留在編譯好的.class文件裏面,在執行的時候,並不會把這一些信息加載到虛擬機(JVM)中去.注意一下,當你沒有設定一個Annotation類型的Retention值時,系統默認值是CLASS.
第三個,是RUNTIME,表示在源碼、編譯好的.class文件中保留信息,在執行的時候會把這一些信息加載到JVM中去的.
  舉一個例子,如@Override裏面的Retention設爲SOURCE,編譯成功了就不要這一些檢查的信息;相反,@Deprecated裏面的Retention設爲RUNTIME,表示除了在編譯時會警告咱們使用了哪一個被Deprecated的方法,在執行的時候也能夠查出該方法是否被Deprecated.


四、源文件ElementType.java

Java代碼 複製代碼
  1. public enum ElementType {
  2. TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR,
  3. LOCAL_VARIABLE, ANNOTATION_TYPE,PACKAGE
  4. }
  1. public enum ElementType {
  2. TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR,
  3. LOCAL_VARIABLE, ANNOTATION_TYPE,PACKAGE
  4. }
public enum ElementType {
    TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR,
    LOCAL_VARIABLE, ANNOTATION_TYPE,PACKAGE
   }


@Target裏面的ElementType是用來指定Annotation類型能夠用在哪一些元素上的.說明一下:TYPE(類型), FIELD(屬性), METHOD(方法), PARAMETER(參數), CONSTRUCTOR(構造函數),LOCAL_VARIABLE(局部變量), ANNOTATION_TYPE,PACKAGE(包),其中的TYPE(類型)是指能夠用在Class,Interface,Enum和Annotation類型上.
另外,從1的源代碼能夠看出,@Target本身也用了本身來聲明本身,只能用在ANNOTATION_TYPE之上.
若是一個Annotation類型沒有指明@Target使用在哪些元素上,那麼它可使用在任何元素之上,這裏的元素指的是上面的八種類型.
舉幾個正確的例子:
@Target(ElementType.METHOD)
@Target(value=ElementType.METHOD)
@Target(ElementType.METHOD,ElementType.CONSTRUCTOR)
具體參考一下javadoc文檔

上面一下1和2的源文件,它們都使用了@Documented,@Documented的目的就是讓這一個Annotation類型的信息可以顯示在javaAPI說明文檔上;沒有添加的話,使用javadoc生成API文檔的時候就會找不到這一個類型生成的信息.
另一點,若是須要把Annotation的數據繼承給子類,那麼就會用到@Inherited這一個Annotation類型.

第三部分:下面講的設計一個最簡單的Annotation例子,這一例子共用四個文件;
一、Description.java

Java代碼 複製代碼
  1. package lighter.javaeye.com;
  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. @Target (ElementType.TYPE)
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Documented
  10. public @interface Description {
  11. String value();
  12. }
  1. package lighter.javaeye.com;
  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. @Target (ElementType.TYPE)
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Documented
  10. public @interface Description {
  11. String value();
  12. }
package lighter.javaeye.com;

   import java.lang.annotation.Documented;
   import java.lang.annotation.ElementType;
   import java.lang.annotation.Retention;
   import java.lang.annotation.RetentionPolicy;
   import java.lang.annotation.Target;

   @Target(ElementType.TYPE)
   @Retention(RetentionPolicy.RUNTIME)
   @Documented
   public @interface Description {
       String value();
   }



說明:全部的Annotation會自動繼承java.lang.annotation這一個接口,因此不能再去繼承別的類或是接口.
最重要的一點,Annotation類型裏面的參數該怎麼設定:
第一,只能用public或默認(default)這兩個訪問權修飾.例如,String value();這裏把方法設爲defaul默認類型.
第二,參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型和String,Enum,Class,annotations等數據類型,以及這一些類型的數組.例如,String value();這裏的參數成員就爲String.
第三,若是隻有一個參數成員,最好把參數名稱設爲"value",後加小括號.例:上面的例子就只有一個參數成員.

二、Name.java

Java代碼 複製代碼
  1. package lighter.javaeye.com;
  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. //注意這裏的@Target與@Description裏的不一樣,參數成員也不一樣
  8. @Target (ElementType.METHOD)
  9. @Retention(RetentionPolicy.RUNTIME)
  10. @Documented
  11. public @interface Name {
  12. String originate();
  13. String community();
  14. }
  1. package lighter.javaeye.com;
  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. //注意這裏的@Target與@Description裏的不一樣,參數成員也不一樣
  8. @Target (ElementType.METHOD)
  9. @Retention(RetentionPolicy.RUNTIME)
  10. @Documented
  11. public @interface Name {
  12. String originate();
  13. String community();
  14. }
package lighter.javaeye.com;

   import java.lang.annotation.Documented;
   import java.lang.annotation.ElementType;
   import java.lang.annotation.Retention;
   import java.lang.annotation.RetentionPolicy;
   import java.lang.annotation.Target;

    //注意這裏的@Target與@Description裏的不一樣,參數成員也不一樣
   @Target(ElementType.METHOD)
   @Retention(RetentionPolicy.RUNTIME)
   @Documented
   public @interface Name {
       String originate();
       String community();
   }



三、JavaEyer.java

Java代碼 複製代碼
  1. package lighter.javaeye.com;
  2. @Description("javaeye,作最棒的軟件開發交流社區")
  3. public class JavaEyer {
  4. @Name (originate="創始人:robbin",community="javaEye")
  5. public String getName()
  6. {
  7. return null;
  8. }
  9. @Name (originate="創始人:江南白衣",community="springside")
  10. public String getName2()
  11. {
  12. return "借用兩位的id一用,寫這一個例子,請見諒!";
  13. }
  14. }
  1. package lighter.javaeye.com;
  2. @Description("javaeye,作最棒的軟件開發交流社區")
  3. public class JavaEyer {
  4. @Name (originate="創始人:robbin",community="javaEye")
  5. public String getName()
  6. {
  7. return null;
  8. }
  9. @Name (originate="創始人:江南白衣",community="springside")
  10. public String getName2()
  11. {
  12. return "借用兩位的id一用,寫這一個例子,請見諒!";
  13. }
  14. }
package lighter.javaeye.com;

@Description("javaeye,作最棒的軟件開發交流社區")
public class JavaEyer {
	@Name(originate="創始人:robbin",community="javaEye")
	public String getName()
	{
		return null;
	}
	
	@Name(originate="創始人:江南白衣",community="springside")
	public String getName2()
	{
		return "借用兩位的id一用,寫這一個例子,請見諒!";
	}
}


四、最後,寫一個能夠運行提取JavaEyer信息的類TestAnnotation

Java代碼 複製代碼
  1. package lighter.javaeye.com;
  2. import java.lang.reflect.Method;
  3. import java.util.HashSet;
  4. import java.util.Set;
  5. public class TestAnnotation {
  6. /**
  7. * author lighter
  8. * 說明:具體關天Annotation的API的用法請參見javaDoc文檔
  9. */
  10. public static void main(String[] args) throws Exception {
  11. String CLASS_NAME = "lighter.javaeye.com.JavaEyer";
  12. Class test = Class.forName(CLASS_NAME);
  13. Method[] method = test.getMethods();
  14. boolean flag = test.isAnnotationPresent(Description.class);
  15. if(flag)
  16. {
  17. Description des = (Description)test.getAnnotation(Description.class);
  18. System.out.println("描述:"+des.value());
  19. System.out.println("-----------------");
  20. }
  21. //把JavaEyer這一類有利用到@Name的所有方法保存到Set中去
  22. Set<Method> set = new HashSet<Method>();
  23. for(int i=0;i<method.length;i++)
  24. {
  25. boolean otherFlag = method[i].isAnnotationPresent(Name.class);
  26. if(otherFlag) set.add(method[i]);
  27. }
  28. for(Method m: set)
  29. {
  30. Name name = m.getAnnotation(Name.class);
  31. System.out.println(name.originate());
  32. System.out.println("建立的社區:"+name.community());
  33. }
  34. }
  35. }
  1. package lighter.javaeye.com;
  2. import java.lang.reflect.Method;
  3. import java.util.HashSet;
  4. import java.util.Set;
  5. public class TestAnnotation {
  6. /**
  7. * author lighter
  8. * 說明:具體關天Annotation的API的用法請參見javaDoc文檔
  9. */
  10. public static void main(String[] args) throws Exception {
  11. String CLASS_NAME = "lighter.javaeye.com.JavaEyer";
  12. Class test = Class.forName(CLASS_NAME);
  13. Method[] method = test.getMethods();
  14. boolean flag = test.isAnnotationPresent(Description.class);
  15. if(flag)
  16. {
  17. Description des = (Description)test.getAnnotation(Description.class);
  18. System.out.println("描述:"+des.value());
  19. System.out.println("-----------------");
  20. }
  21. //把JavaEyer這一類有利用到@Name的所有方法保存到Set中去
  22. Set<Method> set = new HashSet<Method>();
  23. for(int i=0;i<method.length;i++)
  24. {
  25. boolean otherFlag = method[i].isAnnotationPresent(Name.class);
  26. if(otherFlag) set.add(method[i]);
  27. }
  28. for(Method m: set)
  29. {
  30. Name name = m.getAnnotation(Name.class);
  31. System.out.println(name.originate());
  32. System.out.println("建立的社區:"+name.community());
  33. }
  34. }
  35. }
package lighter.javaeye.com;

  import java.lang.reflect.Method;
  import java.util.HashSet;
  import java.util.Set;

  public class TestAnnotation {
	/**
	 * author lighter
	 * 說明:具體關天Annotation的API的用法請參見javaDoc文檔
	 */
       public static void main(String[] args) throws Exception {
       String  CLASS_NAME = "lighter.javaeye.com.JavaEyer";
       Class  test = Class.forName(CLASS_NAME);
       Method[] method = test.getMethods();
       boolean flag = test.isAnnotationPresent(Description.class);
        if(flag)
        {
        	Description des = (Description)test.getAnnotation(Description.class);
        	System.out.println("描述:"+des.value());
        	System.out.println("-----------------");
        }
        
        //把JavaEyer這一類有利用到@Name的所有方法保存到Set中去
        Set<Method> set = new HashSet<Method>();
        for(int i=0;i<method.length;i++)
        {
        	boolean otherFlag = method[i].isAnnotationPresent(Name.class);
        	if(otherFlag) set.add(method[i]);
        }
        for(Method m: set)
        {
        	Name name = m.getAnnotation(Name.class);
        	System.out.println(name.originate());
        	System.out.println("建立的社區:"+name.community());
        }
     }
}
 
 
Java註解 

一、什麼是java註解 
註解,顧名思義,註解,就是對某一事物進行添加註釋說明,會存放一些信息,這些信息可能對之後某個時段來講是頗有用處的。 
Java註解又叫java標註,java提供了一套機制,使得咱們能夠對方法、類、參數、包、域以及變量等添加標準(即附上某些信息)。且在之後某個時段經過反射將標註的信息提取出來以供使用。 

2 爲何要自定義註解 
Java從1.5版本之後默認內置三個標註: 
Ø @Override:只能用在方法之上的,用來告訴別人這一個方法是改寫父類的。 
Ø @Deprecated:建議別人不要使用舊的API的時候用的,編譯的時候會用產生警告信息,能夠設定在程序裏的全部的元素上. 
Ø @SuppressWarnings:這一個類型能夠來暫時把一些警告信息消息關閉. 
可是,僅僅這三個標註是不能知足咱們開發時一些需求的。因此java容許咱們自定義註解來使用。 
3 爲何要自定義註解 
Java從1.5版本之後默認內置三個標註: 
Ø @Override:只能用在方法之上的,用來告訴別人這一個方法是改寫父類的。 
Ø @Deprecated:建議別人不要使用舊的API的時候用的,編譯的時候會用產生警告信息,能夠設定在程序裏的全部的元素上. 
Ø @SuppressWarnings:這一個類型能夠來暫時把一些警告信息消息關閉. 
可是,僅僅這三個標註是不能知足咱們開發時一些需求的。因此java容許咱們自定義註解來使用。 
4 如何自定義註解 
自定義步驟大體分爲兩步: 
1, 經過@interface關鍵字(注意,不是interface,是@interace)聲明註解名稱,以及註解的成員屬性或者叫作註解的參數。 
2, 使用java內置的四個元註解對這個自定義標註的功能和範圍進行一些限制 
問題來了,什麼是元註解? 
5 什麼是元註解 
元註解,就是定義註解的註解,也就是說這些元註解是的做用就是專門用來約束其它註解的註解。請區別上面那三個註解,他們也是經過元註解定義而來的。 
元註解有哪些呢,主要有四個@Target,@Retention,@Documented,@Inherited?  註解的應用圖  自定義註解  自定義一個類級別的標註Description 
package lighter.javaeye.com; 
import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 
@Target(ElementType.TYPE)//這個標註應用於類 
@Retention(RetentionPolicy.RUNTIME)//標註會一直保留到運行時 
@Documented//將此註解包含在javadoc中 
public @interface Description { 
String value(); 
} 
再定義個方法級別的註解Name 
package lighter.javaeye.com; 
import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 
//注意這裏的@Target與@Description裏的不一樣,參數成員也不一樣 
@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface Name { 
String originate(); 
String community(); 
} 
而後使用以上兩個註解 
package lighter.javaeye.com; 
@Description(value="javaeye,作最棒的軟件開發交流社區") 
public class JavaEyer { 
@Name(originate="創始人:robbin",community="javaEye") 
public String getName() 
{ 
return null; 
} 
@Name(originate="創始人:江南白衣",community="springside") 
public String getName2() 
{ 
return "借用兩位的id一用,寫這一個例子,請見諒!"; 
} 
} 
說明:其中標註「@Description(value="javaeye,作最棒的軟件開發交流社區")」,能夠寫成「@Description("javaeye,作最棒的軟件開發交流社區") 」,結果也是同樣的。由於Description標註定義的時候其參數(或者說屬性)爲value。而value比較特殊,它在被指定參數的時候能夠不用顯示的寫出來。固然若是定義的時候參數名不是value而是其它的好比des,那麼使用註解的時候,必須顯示寫出參數名,而後再賦值:@Description(Des=」xxx」) 
提取出註解的信息 
package lighter.javaeye.com; 
import java.lang.reflect.Method; 
import java.util.HashSet; 
import java.util.Set; 
public class TestAnnotation { 
/** 
* author lighter 
* 說明:具體關天Annotation的API的用法請參見javaDoc文檔 
*/ 
public static void main(String[] args) throws Exception { 
String CLASS_NAME = "lighter.javaeye.com.JavaEyer"; 
Class test = Class.forName(CLASS_NAME); 
Method[] method = test.getMethods(); 
boolean flag = test.isAnnotationPresent(Description.class); 
if(flag) 
{ 
Description des = (Description)test.getAnnotation(Description.class); 
System.out.println("描述:"+des.value()); 
System.out.println("-----------------"); 
} 
//把JavaEyer這一類有利用到@Name的所有方法保存到Set中去 
Set<Method> set = new HashSet<Method>(); 
for(int i=0;i<method.length;i++) 
{ 
boolean otherFlag = method[i].isAnnotationPresent(Name.class); 
if(otherFlag) set.add(method[i]); 
} 
for(Method m: set) 
{ 
Name name = m.getAnnotation(Name.class); 
System.out.println(name.originate()); 
System.out.println("建立的社區:"+name.community()); 
} 
} 
}
相關文章
相關標籤/搜索