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

什麼是註解?

註解的定義

官網描述如下:

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

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

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

Java中的元數據和元編程

註解的分類

一般常用的註解可以分爲三類:

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

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

3、自定義註解
用戶可以根據自己的需求定義註解。

註解的使用

使用Java自帶的註解

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


    @Override         //在需要註解的方法上面@Override即可
    protected void onCreate() {
      
    }

常用的Java註解如下:

1、@Deprecated – 所標註內容不再被建議使用;
2、@Override – 只能標註方法,表示該方法覆蓋父類中的方法;
3、@Documented --所標註內容可以出現在javadoc中;
4、@Inherited – 只能被用來標註“Annotation類型”,它所標註的Annotation具有繼承性;
5、@Retention – 只能被用來標註“Annotation類型”,而且它被用來指定Annotation的RetentionPolicy屬性;
6、@Target – 只能被用來標註“Annotation類型”,而且它被用來指定Annotation的ElementType屬性;
7、@SuppressWarnings – 所標註內容產生的警告,編譯器會對這些警告保持靜默;
8、@interface – 用於定義一個註解;

其中,4、5、6、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)的架構如下:
在這裏插入圖片描述

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

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

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

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

註解的作用

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

  • 註解:是一種分散式的元數據,與源代碼緊綁定。
  • xml:是一種集中式的元數據,與源代碼無綁定

這部分多用於Java後臺的配置項開發中,我們知道幾年前服務器的配置項多存放在一個xml文件中,而spring 2.5 之後開始基於註解配置,從而實現了代替配置文件的功能。

註解的用途有很多,上面的只是一個簡單的例子,總起起來,註解有如下四大部分作用:

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

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

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

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

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