自定義注解那些事


Referencehttps://www.cnblogs.com/chanshuyi/p/annotation_serial_02_self_define_annotation.html

自定義注解是自己寫框架的必備技能,使用注解能極大地提升開發效率,因此自定義注解是一個高級開發者必備的技能。

要自定義注解,首先需要了解一個注解的構成部分。

一個注解大致可以分為三個部分:注解體、元注解、注解屬性

在在這三個主要組成部分中,注解體指定了注解的名字,而元注解則標記了該注解的使用場景、留存時間等信息,而注解屬性則指明該注解擁有的屬性。

注解體

注解體是最簡單的一個組成部分,只需要實例中一樣有樣學樣即可。與接口的聲明唯一的不同是在 interface 關鍵字前多了一個 @ 符號

//聲明了一個名為sweet的注解體 @Retention(RetentionPolicy.RUNTIME) public @interface sweet{ }

元注解

元注解(meta-annotation)本身也是一個注解,用來標記普通注解的存留時間、使用場景、繼承屬性、文檔生成信息。

元注解是一個特殊的注解,它是 Java 源碼中就自帶的注解。在Java 中只有四個元注解,它們分別是:@Target、@Retention、@Documented、@Inherited。

@Target注解

Target 注解限定了該注解的使用場景。

它有下面這些取值:

  • ElementType.ANNOTATION_TYPE 可以給一個注解進行注解
  • ElementType.CONSTRUCTOR 可以給構造方法進行注解
  • ElementType.FIELD 可以給屬性進行注解
  • ElementType.LOCAL_VARIABLE 可以給局部變量進行注解
  • ElementType.METHOD 可以給方法進行注解
  • ElementType.PACKAGE 可以給一個包進行注解
  • ElementType.PARAMETER 可以給一個方法內的參數進行注解
  • ElementType.TYPE 可以給一個類型進行注解,比如類、接口、枚舉
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) public @interface Autowired { boolean required() default true; }

在上面 Autowire的 注解中,其 Target 注解的值為 CONSTRUCTOR、METHOD、PARAMETER、FIELD、ANNOTATION_TYPE 這 5 個值。這表示 Autowired 注解只能在構造方法、方法、方法形參、屬性、類型這 5 種場景下使用。

@Retention注解

Retention 注解用來標記這個注解的留存時間。

它其有四個可選值:

  • RetentionPolicy.SOURCE注解只在源碼階段保留,在編譯器進行編譯時它將被丟棄忽視。
  • RetentionPolicy.CLASS注解只被保留到編譯進行的時候,它並不會被加載到 JVM 中。
  • RetentionPolicy.RUNTIME注解可以保留到程序運行的時候,它會被加載進入到 JVM 中,所以在程序運行時可以獲取到它們。
@Retention(RetentionPolicy.RUNTIME) public @interface Autowired { boolean required() default true; }

在上面 Autowire的 注解中,其 Retention 注解的值為 RetentionPolicy.RUNTIME,說明該注解會保留到程序運行的時候。

@Documented

@ Documented 注解表示:將注解信息寫入到 javadoc 文檔中。

在默認情況下,我們的注解信息是不會寫入到 Javadoc 文檔中的。但如果該注解有 @Documented 標識,那么該注解信息則會寫入到 javadoc 文檔中。

例如在下面這個例子中,我們聲明了一個 @Spicy 的注解,沒有 @Documented 元注解。

public @interface Spicy { String spicyLevel(); }

聲明一個 @Sweet 注解,有 @Documented 元注解。

@Documented public @interface Sweet { String sweetLevel(); }

接下來寫一個 SweetDemo 類,類中的 sweetWithDoc 方法使用 @Sweet 注解,spicyWithoutDoc 方法使用 @Spicy 注解。

public class SweetDemo { public static void main(String arg[]) { new SweetDemo().sweetWithDoc(); new SweetDemo().spicyWithoutDoc(); } @Sweet (sweetLevel="Level.05") public void sweetWithDoc() { System.out.printf("sweet With Doc."); } @Spicy (spicyLevel="Level.04") public void spicyWithoutDoc() { System.out.printf("spicy Without Doc."); } }

最后我們使用 Javadoc 命令去生成對應的 JavaDoc 文檔,打開文檔你會看到:sweetWithDoc方法上面有一個注解信息,而 spicyWithoutDoc 方法上卻沒有注解信息。

這個就是 @Documented 這個元注解的作用。

@Inherited

@ Inherited注解標識子類將繼承父類的注解屬性。

在下面的例子中,我們聲明了一個 Sweet 注解,接着在 Peach 類使用了 @Sweet 注解,但是並沒有在 RedPeach 類使用該注解。

//聲明一個Sweet注解,標識甜味。 @Inherited @Retention(RetentionPolicy.RUNTIME) @interface Sweet {} //桃子有甜味 @Sweet public class Peach {} //紅色的水蜜桃 public class RedPeach extends Peach {}

雖然我們沒在 RedPeach 類上使用了 @Sweet 注解,但是我們在 Sweet 注解聲明中使用了 @Inherited 注解,所以 RedPeach 繼承了 Peach 的 @Sweet 注解。

注解屬性

注解屬性類似於類方法的聲明,注解屬性里有三部分信息,分別是:屬性名、數據類型、默認值。

在 @Autowired 注解中就聲明了一個名為 required 的 boolean 類型數據,其默認值是 true。

public @interface Autowired { boolean required() default true; }

需要注意的是,注解中定義的屬性,它的數據類型必須是 8 種基本數據類型(byte、short、int、long、float、double、boolean、char)或者是類、接口、注解及它們的數組。

總結

一個注解大致可以分為三個部分:注解體、元注解、注解屬性。在這三個主要組成部分中:

注解體指定了注解的名字、

元注解則標記了該注解的使用信息,

注解屬性指明注解的屬性。


免責聲明!

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



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