Java註解總結(史上最全,有這一篇就夠了)

什麼是註解?

註解的定義

官網描述以下:java

Java 註解用於爲 Java 代碼提供元數據。做爲元數據,註解不直接影響你的代碼執行,但也有一些類型的註解實際上能夠用於這一目的。Java 註解是從 Java5 開始添加到 Java 的。spring

將上面的話再翻譯一下,以下:
(1)元數據在開發中的做用就是作數據約束和標準定義,能夠將其理解成代碼的規範標準(代碼的模板);
(2)代碼的模板(元數據)不直接影響代碼的執行,它只是幫助咱們來更快捷的開發;服務器

綜上,註解是一種元數據,能夠將它理解爲註釋、解釋,它爲咱們在代碼中添加信息提供了一種形式化的方法,它用於幫助咱們更快捷的寫代碼。markdown

註解的分類

通常經常使用的註解能夠分爲三類: 架構

一、Java自帶的標準註解
包括@Override、@Deprecated、@SuppressWarnings等,使用這些註解後編譯器就會進行檢查。ide

二、元註解
元註解是用於定義註解的註解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等。
元註解也是Java自帶的標準註解,只不過用於修飾註解,比較特殊。函數

三、自定義註解
用戶能夠根據本身的需求定義註解。源碼分析

註解的使用

使用Java自帶的註解
Java 自帶的註解,就是 java.lang中定義的一套註解,以Override註解爲例,使用方法以下:翻譯

@Override         //在須要註解的方法上面@Override便可
protected void onCreate() {

}

經常使用的Java註解以下:code

一、@Deprecated – 所標註內容再也不被建議使用;
二、@Override – 只能標註方法,表示該方法覆蓋父類中的方法;
三、@Documented --所標註內容能夠出如今javadoc中;
四、@Inherited – 只能被用來標註「Annotation類型」,它所標註的Annotation具備繼承性;
五、@Retention – 只能被用來標註「Annotation類型」,並且它被用來指定Annotation的RetentionPolicy屬性;
六、@Target – 只能被用來標註「Annotation類型」,並且它被用來指定Annotation的ElementType屬性;
七、@SuppressWarnings – 所標註內容產生的警告,編譯器會對這些警告保持靜默;
八、@interface – 用於定義一個註解;

其中,四、五、六、8多用於自定義註解,讀者着重記一下。

自定義註解

在Java中,咱們使用@interface註解來自定義一個註解,以下:

public @interface MyTestAnnotation {

}

此時,咱們已經定義了一個註解MyTestAnnotation ,接着咱們就能夠在類或者方法上做用咱們剛剛新建的註解:

@MyTestAnnotation
public class Test {
   @MyTestAnnotation
   public static void testString(){
   }
}

此時,咱們已經自定義了一個註解,不過如今這個註解毫無心義。

要如何使註解工做呢?這就須要使用元註解了。

經常使用的元註解有@Retention、 @Target、 @Document、 @Inherited和@Repeatable五個。

@Retention
Retention英文意思有保留、保持的意思,它表示註解存在階段是保留在源碼(編譯期),字節碼(類加載)或者運行期(JVM中運行)。

在@Retention註解中使用枚舉RetentionPolicy來表示註解保留時期:

  • @Retention(RetentionPolicy.SOURCE),註解僅存在於源碼中,在class字節碼文件中不包含
  • @Retention(RetentionPolicy.CLASS), 默認的保留策略,註解會在class字節碼文件中存在,但運行時沒法得到
  • @Retention(RetentionPolicy.RUNTIME), 註解會在class字節碼文件中存在,在運行時能夠經過反射獲取到

若是咱們是自定義註解,則經過前面分析,咱們自定義註解若是隻存着源碼中或者字節碼文件中就沒法發揮做用,而在運行期間能獲取到註解才能實現咱們目的,因此自定義註解中確定是使用 @Retention(RetentionPolicy.RUNTIME),以下:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyTestAnnotation {

}

@Target
Target的英文意思是目標,這也很容易理解,使用@Target元註解表示咱們的註解做用的範圍就比較具體了,能夠是類,方法,方法參數變量等,一樣也是經過枚舉類ElementType表達做用類型:

  • @Target(ElementType.TYPE) 做用接口、類、枚舉、註解
  • @Target(ElementType.FIELD) 做用屬性字段、枚舉的常量
  • @Target(ElementType.METHOD) 做用方法
  • @Target(ElementType.PARAMETER) 做用方法參數
  • @Target(ElementType.CONSTRUCTOR) 做用構造函數
  • @Target(ElementType.LOCAL_VARIABLE)做用局部變量
  • @Target(ElementType.ANNOTATION_TYPE)做用於註解(@Retention註解中就使用該屬性)
  • @Target(ElementType.PACKAGE) 做用於包
  • @Target(ElementType.TYPE_PARAMETER) 做用於類型泛型,即泛型方法、泛型類、泛型接口 (jdk1.8加入)
  • @Target(ElementType.TYPE_USE) 類型使用.能夠用於標註任意類型除了 class (jdk1.8加入)

通常比較經常使用的是ElementType.TYPE類型,以下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyTestAnnotation {

}

@Documented
Document的英文意思是文檔。它的做用是可以將註解中的元素包含到 Javadoc 中去。

@Inherited
Inherited的英文意思是繼承,可是這個繼承和咱們平時理解的繼承大同小異,一個被@Inherited註解了的註解修飾了一個父類,若是他的子類沒有被其餘註解修飾,則它的子類也繼承了父類的註解。

@Repeatable
Repeatable的英文意思是可重複的。顧名思義說明被這個元註解修飾的註解能夠同時做用一個對象屢次,可是每次做用註解又能夠表明不一樣的含義。

註解的源碼分析
咱們以@Override註解爲例,來分析其源碼,想查看一個普通類同樣,按住ctrl鍵點擊@Override便可進入其源碼,以下:

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

咱們看到@Override註解就是經過@interface註解定義的一個普通註解,而咱們知道,使用 @interface 定義註解時,意味着它實現了 java.lang.annotation.Annotation 接口,即該註解就是一個Annotation

注意:定義 Annotation 時,@interface 是必須的,它和咱們一般的 implemented 實現接口的方法不一樣。Annotation 接口的實現細節都由編譯器完成。經過 @interface 定義註解後,該註解不能繼承其餘的註解或接口。

下面咱們來分析一下Annotation 類的源碼,以下:

public interface Annotation {
    boolean equals(Object var1);

    int hashCode();

    String toString();

    Class<? extends Annotation> annotationType();
}

經過以上源碼,咱們知道註解自己就是Annotation接口的子接口,也就是說註解中實際上是能夠有屬性和方法,可是接口中的屬性都是static final的,對於註解來講沒什麼意義,而咱們定義接口的方法就至關於註解的屬性,也就對應了前面說的爲何註解只有屬性成員變量,其實他就是接口的方法,這就是爲何成員變量會有括號,不一樣於接口咱們能夠在註解的括號中給成員變量賦值。

Java註解的架構

根據上述的源碼分析,咱們得出Java註解(Annotation)的架構以下:

Java註解總結(史上最全,有這一篇就夠了)

0、註解是接口類,都繼承自Annotation接口類

一、1 個 Annotation 和 1 個 RetentionPolicy 關聯
能夠理解爲:每1個Annotation對象,都會有惟一的RetentionPolicy屬性;

二、1 個 Annotation 和 1~n 個 ElementType 關聯
能夠理解爲:對於每 1 個 Annotation 對象,能夠有若干個 ElementType 屬性;

三、Annotation 有許多實現類,包括:Deprecated, Documented, Inherited, Override 等等。
Annotation 的每個實現類都和1個 RetentionPolicy 關聯而且和 1~n 個 ElementType 關聯。

註解的做用

在說註解的用途以前,咱們先介紹下XML和註解區別:

  • 註解:是一種分散式的元數據,與源代碼緊綁定。
    xml:是一種集中式的元數據,與源代碼無綁定
    這部分多用於Java後臺的配置項開發中,咱們知道幾年前服務器的配置項多存放在一個xml文件中,而spring 2.5 以後開始基於註解配置,從而實現了代替配置文件的功能。

註解的用途有不少,上面的只是一個簡單的例子,總起起來,註解有以下四大部分做用:

一、生成文檔,經過代碼裏標識的元數據生成javadoc文檔。

二、編譯檢查,經過代碼裏標識的元數據讓編譯器在編譯期間進行檢查驗證。

三、編譯時動態處理,編譯時經過代碼裏標識的元數據動態處理,例如動態生成代碼。

四、運行時動態處理,運行時經過代碼裏標識的元數據動態處理,例如使用反射注入實例

相關文章
相關標籤/搜索