天天看點

java 中繼資料 注解_Java:注解Annotation(中繼資料)

本文内容:

注解Annotation的介紹

基本注解的用法

自定義注解

首發日期:2018-07-28

注解Annotation的介紹

Annotation是代碼中的特殊标記,能夠在編譯、類加載、運作時被識别(需要設定),并根據不同的Annotation來執行不同的處理。

Annotation可以修飾包、類、構造器、函數、成員變量、局部變量的聲明、參數等程式元素。Annotation幫助這些元素來設定中繼資料,程式從中繼資料中擷取資訊來處理這些元素。

中繼資料可以描述代碼間關系或者代碼與其它資源的關系,比如說在web.xml中需要将請求路徑跟處理請求的servlet對應起來,比如說在Hibernate中需要.hbm檔案來描述實體類與資料表之間的映射關系。中繼資料可以提供某些資訊來協助我們程式的運作。

在Java中,Annotation就可以幫我們在代碼層面上去設定中繼資料,而不必需要去使用一些例如web.xml的檔案來描述。

基本注解的用法

如何使用注解修飾元素:

通常來說,在修飾目标的上一行進行注解,比如

java 中繼資料 注解_Java:注解Annotation(中繼資料)

。修飾成員變量也是如此。

常用的基本的Annotation:

@Override :指明下面修飾的函數必須是重寫父類的函數的函數,如果修飾的函數不在父類中存在,那麼會報錯。

@Deprecated :标明函數、類等元素已過時,效果是在使用已經過時的元素時會警告。

@SuppressWarnings:抑制修飾的元素發生警告(warning),效果是修飾過後,編譯器不會提示警告。

@SafeVarargs【Java7新增】:如果把一個沒有定義泛型的集合,賦給一個有定義泛型的集合,會發生堆污染,會報錯。@SafeVarargs可以抑制這個報錯。

@FunctionalInterface【Java8新增】:用來限制修飾的接口必須是一個函數式接口,不然會報錯。

元Annotaion:修飾注解的注解

@Retention:指定Annotation的保留方式,保留方式不同,會影響能被使用的位置。比如如果需要通過反射擷取資訊,那麼應該允許運作時還能擷取。

@Retention(RetentionPolicy.CLASS):預設值,代表把注解留在class檔案中,程式運作後,JVM将無法擷取注解。【由于裡面的成員變量名為value,是以可以省去 參數名="xxx",如果不是value,那麼不可以省去!】

@Retention(RetentionPolicy.RUNTIME):代表把注解留在class檔案中,程式運作後,JVM可以通過反射來擷取注解。

@Retention(RetentionPolicy.SOURCE):隻留在源代碼中,JVM不會擷取到注解。

@Target:限制Annotaion能修飾哪些元素

@Target(ElemenetType.ANNOTATION_TYPE):指定被修飾的Annotaion隻能用來修飾Annotaion

@Target(ElemenetType.FIELD):指定被修飾的Annotaion隻能用來修飾成員變量

@Target(ElemenetType.CONSTRUCTOR):指定被修飾的Annotaion隻能用來修飾構造器

@Target(ElemenetType.METHOD):指定被修飾的Annotaion隻能用來修飾函數

@Target(ElemenetType.LOCAL_VARIABLE):指定被修飾的Annotaion隻能用來修飾局部變量

@Target(ElemenetType.PACKAGE):指定被修飾的Annotaion隻能用來修飾包

@Target(ElemenetType.PARAMETER):指定被修飾的Annotaion隻能用來修飾參數

@Target(ElemenetType.TYPE):指定被修飾的Annotaion隻能用來修飾類、接口(包括注解類型)或枚舉定義

@Documented:指定Annotaion是否能包含到javadoc生成的文檔中。

@Inherited:指定Annotaion具有繼承性,父類定義了這個注解,那麼子類也會繼承這個注解。

自定義注解

自定義注解跟定義接口差不多,在interface的基礎上加一個@

java 中繼資料 注解_Java:注解Annotation(中繼資料)

當就是這麼空,不寫東西的時候,是一個标記型的注解,标記型的注解功能比較簡單,通常隻能用來标記特殊的元素進而進行處理。比如Override就是一個标記型的注解。

注解可以定義成員變量,這些成員變量以聲明無形參函數的形式存在,傳回值是變量的類型,函數名是變量的名字。注解上定義的成員變量隻能是String、數組、Class、枚舉類、注解。成員變量可以提供更多的中繼資料資訊。

java 中繼資料 注解_Java:注解Annotation(中繼資料)

定義了成員變量後,在使用的時候需要給成員變量指派(成員變量名為value時,可以省去value="xxx",但是這個名字時,不可以省略)。在沒有成員變量時,可以單寫注解名,要指派時就要用上括号。

java 中繼資料 注解_Java:注解Annotation(中繼資料)

如果某些成員變量不需要每次都指派,可以給它設定預設值。成員變量可以有預設值,在變量的後面加上default 預設值.

java 中繼資料 注解_Java:注解Annotation(中繼資料)

注解處理器:

對于Java自帶的注解,Java有自己的注解處理器去處理。但自定義的注解,需要自己去定義注解處理器,自己去調用注解處理器去處理。是以,注解處理器本質上也是一個普通函數,不過它的工作主要是處理注解罷了。

在學會怎麼定義注解處理器之前先了解幾個前置知識:

所有注解的父接口都是Annotation。

一個注解,隻有它的存在時間足夠我們才能使用它,是以如果我們想使用注解處理器,注解首先需要使用@Retention(RetentionPolicy.RUNTIME)修飾。

java.lang.reflect包中存在一些能夠實作反射功能的工具類。

java.lang.reflect包中有一個AnnotationElement接口,它聲明了一系列可以擷取注解的函數,并且它有幾個實作類,如下所見,是以你可以在類、構造函數等對象中調用聲明好的函數來擷取注解。

java 中繼資料 注解_Java:注解Annotation(中繼資料)

getAnnotation(注解.class):擷取對應類型的注解

getAnnotations():擷取所有注解

getDeclaredAnnotations():擷取直接注解,忽略繼承過來的注解。

isAnnotationPresent(注解.class):判斷對應類型的注解是否存在

擷取注解:

java 中繼資料 注解_Java:注解Annotation(中繼資料)
java 中繼資料 注解_Java:注解Annotation(中繼資料)

....其他對象就示範了。

操作注解:通常來說,都是處理注解帶上的資訊。

java 中繼資料 注解_Java:注解Annotation(中繼資料)

小例子

不知道你有沒有了解過org.junit.Test這個東西,這個可以讓你直接運作你想要運作的函數(可以稱為單元測試?)。而不需要你建立一個main()去調用。

下面做一個示例,來實作類似的功能:

1.建立注解:

java 中繼資料 注解_Java:注解Annotation(中繼資料)

2.使用注解:

java 中繼資料 注解_Java:注解Annotation(中繼資料)

3.調用注解處理器:【這裡使用了org.junit.Test來調用,你也可以在main()中調用!】

java 中繼資料 注解_Java:注解Annotation(中繼資料)

結果是:

java 中繼資料 注解_Java:注解Annotation(中繼資料)

補充:

上面的小例子中并沒有使用注解的成員變量,但事實上,使用成員變量也同樣隻是擷取裡面的資訊來做更多處理罷了,這就依靠個人去應用了。