Java 注解基本原理


原文地址

注解的本質

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

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

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

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

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

    public interface Override extends Annotation{
        
    }

沒錯,注解的本質就是一個繼承了 Annotation 接口的接口。有關這一點,你可以去反編譯任意一個注解類,你會得到結果的。

一個注解准確意義上來說,只不過是一種特殊的注釋而已,如果沒有解析它的代碼,它可能連注釋都不如。

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

元注解

『元注解』是用於修飾注解的注解,通常用在注解的定義上。

JAVA 中有以下幾個『元注解』:

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

@Target

@Target 注解指明該注解可以作用哪些對象上。

    @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注解基本原理

原文首發在我的簡書 [https://www.jianshu.com/p/c342606e255d](https://www.jianshu.com/p/c342606e255d


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM