Java 註解基本原理

註解的本質

「java.lang.annotation.Annotation」接口中有這麼一句話,用來描述『註解』。html

The common interface extended by all annotation types
全部的註解類型都繼承自這個普通的接口(Annotation)

這句話有點抽象,但卻說出了註解的本質。咱們看一個 JDK 內置註解的定義:java

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

這是註解 @Override 的定義,其實它本質上就是:數組

public interface Override extends Annotation{
}

沒錯,註解的本質就是一個繼承了 Annotation 接口的接口。有關這一點,你能夠去反編譯任意一個註解類,你會獲得結果的。app

一個註解準確意義上來講,只不過是一種特殊的註釋而已,若是沒有解析它的代碼,它可能連註釋都不如。ide

解析一個類或者方法的註解每每有兩種形式,一種是編譯期直接的掃描,一種是運行期反射。code

元註解

『元註解』是用於修飾註解的註解,一般用在註解的定義上。htm

JAVA 中有如下幾個『元註解』:對象

  • @Target:註解的做用目標
  • @Retention:註解的生命週期
  • @Documented:註解是否應當被包含在 JavaDoc 文檔中
  • @Inherited:是否容許子類繼承該註解

@Target

@Target 註解指明該註解能夠做用哪些對象上。blog

@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();
}

註解接收一個ElementType數組,ElementType是一個枚舉,成員以下:繼承

  • ElementType.TYPE:容許被修飾的註解做用在類、接口和枚舉上
  • ElementType.FIELD:容許做用在屬性字段上
  • ElementType.METHOD:容許做用在方法上
  • ElementType.PARAMETER:容許做用在方法參數上
  • ElementType.CONSTRUCTOR:容許做用在構造器上
  • ElementType.LOCAL_VARIABLE:容許做用在本地局部變量上
  • ElementType.ANNOTATION_TYPE:容許做用在註解上
  • ElementType.PACKAGE:容許做用在包上
  • ElementType.TYPE_PARAMETER:容許做用在類型參數上
  • ElementType.TYPE_USE:容許做用在類型上

@Retention

@Retention 用於指明當前註解的生命週期

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
        * Returns the retention policy.
        * @return the retention policy
        */
    RetentionPolicy value();
}

註解接收一個RetentionPolicy數據,RetentionPolicy是個枚舉,成員以下:

  • RetentionPolicy.SOURCE:當前註解編譯期可見,不會寫入 class 文件
  • RetentionPolicy.CLASS:類加載階段丟棄,會寫入 class 文件
  • RetentionPolicy.RUNTIME:永久保存,能夠反射獲取

JAVA 的內置三大註解

  • @Override
  • @Deprecated 標識類或方法再也不推薦使用
  • @SuppressWarnings 主要用來壓制 java 的警告

實現一個本身的註解

定義一個註解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HelloAnnotation {
    String value() default "Hello annotation!";
}

使用這個註解:

public class UseAnnotation {

    @HelloAnnotation
    public void hello() {
        System.out.println("hello");
    }

    @HelloAnnotation("Hello world!")
    public void helloWorld() {
        System.out.println("Hello world!");
    }
}

註解最重要的部分在於對註解的處理。註解處理器就是經過反射機制獲取被檢查方法上的註解信息,而後根據註解元素的值進行特定的處理。若是沒有註解處理器,註解就是個註釋,或者連註釋都不如。

處理這個註解:

public class Test {

    public static void main(String[] args) {
        testAnnotation(UseAnnotation.class);
    }

    private static void testAnnotation(Class<?> cl) {
        for (Method m : cl.getDeclaredMethods()) {
            HelloAnnotation ha = m.getAnnotation(HelloAnnotation.class);
            if (ha != null) {
                System.out.println("Found My Annotation: " + ha.value());
            }
        }
    }
}

輸出結果:

Found My Annotation: Hello annotation!
Found My Annotation: Hello world!

參考資料

JAVA 註解的基本原理
Java註解基本原理

相關文章
相關標籤/搜索