參考:java
- 秒懂,Java 註解 (Annotation)你能夠這樣學
- 瘋狂java講義
同 classs
和 interface
同樣,註解也屬於一種類型。
註解經過 @interface
關鍵字進行定義。數組
public @interface TestAnnotation { }
默認狀況下,Annotation可用於修飾任何程序元素,包括接口、類、方法等。app
Annotation成員變量
以方法形式定義Annotation中的成員變量以無形參的方法形式來聲明。定義了幾個成員變量,在使用時必須給值。ide
public @interface MyTag { String name(); int age(); }
有個默認值,在使用時能夠不給值。工具
public @interface MyTag { String name() default "hobe"; int age() default 18; }
Annotation
jdk除了java.lang下的5個基本Annotation:.net
以外,java.lang.annotation
包下提供了6個Meta Annotation
(元Annotation),其中5個都用於修飾其餘Annotation
。主要幾個以下:code
只能修飾Annotation定義,指定修飾多長時間,其源碼:orm
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { /** * Returns the retention policy. * @return the retention policy */ RetentionPolicy value(); }
其中只有一個成員變量。blog
public enum RetentionPolicy { /** * Annotations are to be discarded by the compiler. */ SOURCE, /** * Annotations are to be recorded in the class file by the compiler * but need not be retained by the VM at run time. This is the default * behavior. */ CLASS, /** * Annotations are to be recorded in the class file by the compiler and * retained by the VM at run time, so they may be read reflectively. * * @see java.lang.reflect.AnnotatedElement */ RUNTIME }
SOURCE
:用於檢查代碼,編譯時丟掉。(主要看IDE是否報錯)CLASS
:(默認)。編譯後也會記錄在class文件中。運行時,JVM不可獲取Annotation信息,不可反射獲取。RUNTIME
:(一般會使用)。編譯後也會記錄在class文件中。運行時,JVM可獲取Annotation信息,可反射獲取。接口
使用示例:
@Retention(RetentionPolicy.RUNTIME) public @interface MyTag { ... }
或:
@Retention(value = RetentionPolicy.RUNTIME) public @interface MyTag { ... }
說明:
當Annotation成員變量名爲value
時,只需爲value指定值時, 能夠在括號裏直接寫出value的值,無需name=value
的形式。
只能修飾Annotation定義。指定哪些程序單元能夠使用,源碼:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { /** * Returns an array of the kinds of elements an annotation type * can be applied to. * @return an array of the kinds of elements an annotation type * can be applied to */ ElementType[] value(); }
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, /** Field declaration (includes enum constants) */ FIELD, /** Method declaration */ METHOD, /** Formal parameter declaration */ PARAMETER, /** Constructor declaration */ CONSTRUCTOR, /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, /** Package declaration */ PACKAGE, /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, /** * Use of a type * * @since 1.8 */ TYPE_USE }
如只能修飾成員變量則使用:
@Target({ElementType.FIELD})
被該Annotation修飾的類將會被javadoc工具提取成文檔。
被@Inherited修飾的註解,用於父類時,子類自動會加該註解。
System.out.println(ChildClass.class.isAnnotationPresent(MyTag.class));
爲true
。
Annotation
標記Annotation
和元數據Annotation
根據Annotation是否包含成員變量,將其分爲兩類:
注意的一種狀況是一個註解沒有任何屬性。好比
public @interface Perform {}
那麼在應用這個註解的時候,括號均可以省略。
@Perform public void testMethod(){}
示例:
@Target({ElementType.FIELD}) @Retention(value = RetentionPolicy.RUNTIME) public @interface MyTag { String name() default "hobe"; //字符串 int age() default 18; //int String[] likes(); // 數組 Sex sex(); //枚舉 }
使用Annotation修飾了類、方法、成員變量等成員以後,這些Annotation並不會本身生效。必須由開發者提取信息並處理。
java.lang.reflect增長了讀取運行時Annotation的能力。如:
如獲取Mytag註解中info方法上的全部註解,則:
Class.forName("MyTag").getMethods("info").getAnnotations()
@Target({ElementType.FIELD,ElementType.TYPE}) @Retention(value = RetentionPolicy.RUNTIME) public @interface MyTag { String name() default "hobe"; //字符串 int age() default 18; //int String[] likes(); // 數組 Sex sex() default Sex.BOY; //枚舉 }
public enum Sex { BOY,GIRL }
@MyTag(likes = {"code","ball"}) public class Demo { private String name; private Integer age; private String[] likes; private Sex sex; public static void main(String[] args) { Demo demo = new Demo(); /** 僅僅註解,並不能將值賦給Demo的字段 */ System.out.println(demo); boolean hasAnnotation = Demo.class.isAnnotationPresent(MyTag.class); if (hasAnnotation){ MyTag myTag = Demo.class.getAnnotation(MyTag.class); System.out.println(myTag.name()); System.out.println(myTag.likes()); System.out.println(myTag.sex()); System.out.println(myTag.age()); } } ... }
結果:
Demo{name='null', age=null, likes=null, sex=null} hobe [Ljava.lang.String;@4617c264 BOY 18
參考:
- 秒懂,Java 註解 (Annotation)你能夠這樣學
- 瘋狂java講義