Java中註解到底是什麼 原

上次在學習@Transactional註解的時候,思考到個問題。Java中的註解到底是什麼?有是如何實現的?

註解是什麼

註解也叫元數據,例如我們常見的@Override和@Deprecated,註解是JDK1.5版本開始引入的一個特性,用於對代碼進行說明,可以對包、類、接口、字段、方法參數、局部變量等進行註解。

註解可分爲三類:

  • 一類是Java自帶的標準註解,包括@Override(標明重寫某個方法)、@Deprecated(標明某個類或方法過時)和@SuppressWarnings(標明要忽略的警告),使用這些註解後編譯器就會進行檢查。

  • 一類爲元註解,元註解是用於定義註解的註解,包括@Retention(標明註解被保留的階段)、@Target(標明註解使用的範圍)、@Inherited(標明註解可繼承)、@Documented(標明是否生成javadoc文檔)

  • 一類爲自定義註解,可以根據自己的需求定義註解

元註解

元註解是可以註解到註解上的註解,或者說元註解是一種基本註解,但是它能夠應用到其它的註解上面。明白點說,就是我們定義註解時用的註解就是元註解。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {


}

除了@符號,註解很像是一個接口。定義註解的時候需要用到元註解。

在註解中一般會有一些元素以表示某些值。註解的元素看起來就像接口的方法,唯一的區別在於可以爲其制定默認值。沒有元素的註解稱爲標記註解,上面的@Test就是一個標記註解。

註解的可用的類型包括以下幾種:所有基本類型、String、Class、enum、Annotation、以上類型的數組形式。元素不能有不確定的值,即要麼有默認值,要麼在使用註解的時候提供元素的值。而且元素不能使用null作爲默認值。註解在只有一個元素且該元素的名稱是value的情況下,在使用註解的時候可以省略“value=”,直接寫需要的值即可。

元註解一共有5種, @Retention、@Documented、@Target、@Inherited、@Repeatable。

  1. Retention

英文意爲保留期的意思。當 @Retention 應用到一個註解上的時候,它解釋說明了這個註解的的存活時間。

它的取值如下:

  • RetentionPolicy.SOURCE 註解只在源碼階段保留,在編譯器進行編譯時它將被丟棄忽視。
  • RetentionPolicy.CLASS 註解只被保留到編譯進行的時候,它並不會被加載到 JVM 中。
  • RetentionPolicy.RUNTIME 註解可以保留到程序運行的時候,它會被加載進入到 JVM 中,所以在程序運行時可以獲取到它們。
  1. @Documented

這個元註解肯定是和文檔有關。它的作用是能夠將註解中的元素包含到 Javadoc 中去

  1. Target

目標的意思,@Target 指定了註解運用的地方

ElementType.ANNOTATION_TYPE 可以給一個註解進行註解 ElementType.CONSTRUCTOR 可以給構造方法進行註解 ElementType.FIELD 可以給屬性進行註解 ElementType.LOCAL_VARIABLE 可以給局部變量進行註解 ElementType.METHOD 可以給方法進行註解 ElementType.PACKAGE 可以給一個包進行註解 ElementType.PARAMETER 可以給一個方法內的參數進行註解 ElementType.TYPE 可以給一個類型進行註解,比如類、接口、枚舉

  1. @Inherited

Inherited 是繼承的意思,但是它並不是說註解本身可以繼承,而是說如果一個超類被 @Inherited 註解過的註解進行註解的話,那麼如果它的子類沒有被任何註解應用的話,那麼這個子類就繼承了超類的註解

  1. @Repeatable

Repeatable 自然是可重複的意思。@Repeatable 是 Java 1.8 才加進來的,所以算是一個新的特性。

什麼樣的註解會多次應用呢?通常是註解的值可以同時取多個。

註解處理器

上面定義的註解,java如何去處理這些註解?這裏用到了java中的反射機制。

需要關注lang包下Class類和AnnotatedElement 接口;

Java.lang.reflect.AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通過反射獲取了某個類的AnnotatedElement對象之後,程序就可以調用該對象的如下四個個方法來訪問Annotation信息:

  方法1:<T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定類型的註解,如果該類型註解不存在,則返回null。

  方法2:Annotation[] getAnnotations():返回該程序元素上存在的所有註解。

  方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判斷該程序元素上是否包含指定類型的註解,存在則返回true,否則返回false.

 方法4:Annotation[] getDeclaredAnnotations():返回直接存在於此元素上的所有註釋。與此接口中的其他方法不同,該方法將忽略繼承的註釋。(如果沒有註釋直接存在於此元素上,則返回長度爲零的一個數組。)該方法的調用者可以隨意修改返回的數組;這不會對其他調用者返回的數組產生任何影響.

Class對象也實現了該接口,即可以獲取目標對象的註解,繼而可以根據註解的屬性,獲得對象的成員變量、方法等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章