手機版
你好,游客 登錄 注冊
背景:
閱讀新聞

Java注解深入理解

[日期:2019-10-10] 來源:Linux社區  作者:Linux [字體: ]

什么是注解?

注解的定義

官網描述如下:

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

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

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

注解的分類

一般常用的注解可以分為三類:

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)的架構如下:

Java注解深入理解

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

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、運行時動態處理,運行時通過代碼里標識的元數據動態處理,例如使用反射注入實例

Linux公社的RSS地址http://www.vnrggh.live/rssFeed.aspx

本文永久更新鏈接地址http://www.vnrggh.live/Linux/2019-10/160960.htm

linux
相關資訊       Java注解 
本文評論   查看全部評論 (0)
表情: 表情 姓名: 字數

       

評論聲明
  • 尊重網上道德,遵守中華人民共和國的各項有關法律法規
  • 承擔一切因您的行為而直接或間接導致的民事或刑事法律責任
  • 本站管理人員有權保留或刪除其管轄留言中的任意內容
  • 本站有權在網站內轉載或引用您的評論
  • 參與本評論即表明您已經閱讀并接受上述條款
彩票平台