java註解

一、概念

   Annontation是Java5開始引入的新特徵。中文名稱一般叫註解也叫元註解。它提供了一種安全的類似註釋的機制,用來將任何的信息或元數據(metadata)與程序元素(類、方法、成員變量等)進行關聯。

  更通俗的意思是爲程序的元素(類、方法、成員變量)加上更直觀更明瞭的說明,這些說明信息是與程序的業務邏輯無關,並且是供指定的工具或框架使用的。

Annontation像一種修飾符一樣,應用於包、類型、構造方法、方法、成員變量、參數及本地變量的聲明語句中

註解的語法比較簡單,除了@符號的使用之外,它基本與Java固有語法一致。

 

一般是不需要自己去定義註解的,除非你要自己寫框架類的東西,如果是,註解是配合反射一起用的,通過反射,可以根據class、field、method等對象拿到它上面標註的註解,然後根據有沒有註解、註解的類型或註解上的參數的不同,來執行不同的操作。

 

 

 

 

二、原理

 

  Annotation其實是一種接口。通過Java的反射機制相關的API來訪問annotation信息。相關類(框架或工具中的類)根據這些信息來決定如何使用該程序元素或改變它們的行爲。

annotation是不會影響程序代碼的執行,無論annotation怎麼變化,代碼都始終如一地執行。

 

  Java語言解釋器在工作時會忽略這些annotation,因此在JVM 中這些annotation是“不起作用”的,只能通過配套的工具才能對這些annontaion類型的信息進行訪問和處理。

  Annotation與interface的異同

    1)、Annotation類型使用關鍵字@interface而不是interface。

這個關鍵字聲明隱含了一個信息:它是繼承了java.lang.annotation.Annotation接口,並非聲明瞭一個interface

    2)、Annotation類型、方法定義是獨特的、受限制的。

  Annotation 類型的方法必須聲明爲無參數、無異常拋出的。這些方法定義了annotation的成員:方法名成爲了成員名,而方法返回值成爲了成員的類型。而方法返回值類型必須爲primitive類型、Class類型、枚舉類型、annotation類型或者由前面類型之一作爲元素的一維數組。方法的後面可以使用 default和一個默認數值來聲明成員的默認值,null不能作爲成員默認值,這與我們在非annotation類型中定義方法有很大不同。

  Annotation類型和它的方法不能使用annotation類型的參數、成員不能是generic。只有返回值類型是Class的方法可以在annotation類型中使用generic,因爲此方法能夠用類轉換將各種類型轉換爲Class。

    3)、Annotation類型又與接口有着近似之處。

 它們可以定義常量、靜態成員類型(比如枚舉類型定義)。Annotation類型也可以如接口一般被實現或者繼承。

三、應用場合

  annotation一般作爲一種輔助途徑,應用在軟件框架或工具中,在這些工具類中根據不同的 annontation註解信息採取不同的處理過程或改變相應程序元素(類、方法及成員變量等)的行爲。

例如:Junit、Struts、Spring等流行工具框架中均廣泛使用了annontion。使代碼的靈活性大提高。

 

1.1 知識點

1.1.1 Java內置註解組成

 

註解的語法比較簡單,除了@符號的使用以外,它基本上與java的固有語法一致,java內置了三種註解,定義在java.lang包中。

註解名稱

描述

@Override

表示當前的方法定義將覆蓋超類中的方法。

@Deprecated

使用了註解爲它的元素編譯器將發出警告,因爲註解@Deprecated是不贊成使用的代碼,被棄用的代碼。

@SuppressWarnings

關閉不當編譯器警告信息。

它可以有以下參數:

deprecation:過時的類或方法警告。

unchecked:執行了未檢查的轉換時警告。

fallthrough:當 Switch 程序塊直接通往下一種情況而沒有 Break 時的警告。

path:在類路徑、源文件路徑等中有不存在的路徑時的警告。

serial:當在可序列化的類上缺少 serialVersionUID 定義時的警告。

finally:任何 finally 子句不能完成時的警告。

all:關於以上所有情況的警告。

 

1.1.2 如何使用註解

註解的實例代碼如下:

public class Dog {

/**

 * 一個普通的方法,讓此方法變成棄用方法

 */

@Deprecated

public void run() {

}

/**

 * 方法裏有未使用的變量i,在eclipse中有警告提示,

 * 如果我們想在警告去掉,可以使用@SuppressWarnings註解。

 *

 */

@SuppressWarnings({"all"})

public void eat() {

int i = 5;

}

/**

 * 重寫Object類中的toString()方法,如果不加@Override

 * 本意是想重寫toString(),但如果方法名稱寫錯了也不會報錯,

 * eclipse認爲這是在子類裏添加了一個新方法,如果加上@Override

 * 這就是重寫,父類中必須有這樣的方法。

 */

@Override

public String toString() {

return super.toString();

}

}

 

1.1.3 創建新註解

和創建一個自定義的類一樣,我們不僅可以使用別人寫好的類,我們也可以創建自已需要的類,註解也一樣,也可以創建系統中不存在的註解。在進行創建新註解時,需要用到原註解,原註解是專門負責新註解的創建的。

 

原註解共有四個,如下描述:

@Retention

它是被定義在一個註解類的前面,用來說明該註解的生命週期。

它有以下參數:

RetentionPolicy.SOURCE :指定註解只保留在一個源文件當中。

RetentionPolicy.CLASS :指定註解只保留在一個 class 文件中。

RetentionPolicy.RUNTIME :指定註解可以保留在程序運行期間。

 

@Target

它是被定義在一個註解類的前面,用來說明該註解可以被聲明在哪些元素前。

它有以下參數:

ElementType.TYPE :說明該註解只能被聲明在一個類前。

ElementType.FIELD :說明該註解只能被聲明在一個類的字段前。

ElementType.METHOD :說明該註解只能被聲明在一個類的方法前。

ElementType.PARAMETER :說明該註解只能被聲明在一個方法參數前。

ElementType.CONSTRUCTOR :說明該註解只能聲明在一個類的構造方法前 。

ElementType.LOCAL_VARIABLE :說明該註解只能聲明在一個局部變量前。

ElementType.ANNOTATION_TYPE :說明該註解只能聲明在一個註解類型前 。

ElementType.PACKAGE :說明該註解只能聲明在一個包名前。

 

@Documented

將註解包含在Javadoc中。

 

@Inherited

允許子類繼承父類中的註解。

 

先來看一下如何編寫一個最簡單的註解類:

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

@Retention(RetentionPolicy.CLASS)

@Target({ElementType.FIELD, ElementType.METHOD})

@Documented

@Inherited

public @interface Fruit {

 

}

 

通過此註解返回給我們的信息有:

² 當在一個註解類前定義了一個 @Retetion(RetentionPolicy.CLASS) 的註解,那麼說明該註解只保留在一個 class 文件當中,當加載 class 文件到內存時,虛擬機會將註解去掉,從而在程序中不能訪問。

² 說明該註解只能被聲明在一個類的屬性和方法前。注意,如果註解類同時可以用到類和方法前,需要用“{}”引起來編寫。

² 在生成文檔時將註解包含在Javadoc中。

² 允許子類繼承父類中的註解。

 

除了@符號,註解很像是一個接口。定義註解的時候需要用到元註解,上面用到了@Target@RetentionPolicy@Documented@Inherited四個原註解。

1.1.4 註解定義

1、註解可以有哪些成員?

註解和接口相似,它只能定義 final 靜態屬性和公共抽象方法。

 

2、註解的方法?

1. 方法前默認會加上 public abstract

2. 在聲明方法時可以定義方法的默認返回值。

例如 :

String color() default "blue";

String[] color() default {"blue", "red",......}

 

3、方法的返回值可以有哪些類型 ?

八種基本類型, String Class 、枚舉、註解及這些類型的數組。

1.1.5 註解生命週期

一個註解可以有三個生命週期,它默認的生命週期是保留在一個 CLASS 文件,但它也可以由一個@Retetion的元註解指定它的生命週期。

java 源文件

當在一個註解類前定義了一個@Retetion(RetentionPolicy.SOURCE) 的註解,那麼說明該註解只保留在一個源文件當中,當編譯器將源文件編譯成 class 文件時,它不會將源文件中定義的註解保留在 class 文件中。

class 文件中

當在一個註解類前定義了一個 @Retetion(RetentionPolicy.CLASS) 的註解,那麼說明該註解只保留在一個 class 文件當中,當加載 class 文件到內存時,虛擬機會將註解去掉,從而在程序中不能訪問。

程序運行期間

當在一個註解類前定義了一個 @Retetion(RetentionPolicy.RUNTIME) 的註解,那麼說明該註解在程序運行期間都會存在內存當中。此時,我們可以通過反射來獲得定義在某個類上的所有註解。

1.1.6 註解的使用

在註解中一般會有一些元素以表示某些值。註解的元素看起來就像接口的方法,唯一的區別在於可以爲其制定默認值。沒有元素的註解稱爲標記註解,上面的@Fruit就是一個標記註解。

 

註解的可用的類型包括以下幾種:所有基本類型、StringClassenumAnnotation、以上類型的數組形式。

 

對註解元素的要求:

ü 元素不能有不確定的值,即要麼有默認值,要麼在使用註解的時候提供元素的值。

ü 元素不能使用null作爲默認值。

ü  註解元素必須有確定的值,要麼在定義註解的默認值中指定,要麼在使用註解時指定,非基本類型的註解元素的值不可爲null。因此, 使用空字符串或0作爲默認值是一種常用的做法。這個約束使得處理器很難表現一個元素的存在或缺失的狀態,因爲每個註解的聲明中,所有元素都存在,並且都具有相應的值,爲了繞開這個約束,我們只能定義一些特殊的值,例如空字符串或者負數,一次表示某個元素不存在,在定義註解時,這已經成爲一個習慣用法。

ü 註解在只有一個元素且該元素的名稱是value的情況下,在使用註解的時候可以省略“value=”,直接寫需要的值即可。

 

繼續使用剛纔的註解類,給裏面添加註解元素,一共添加三個,一個是常量元素,兩個是普通元素,兩個普通元素一個有默認值,一個沒有默認值。

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

/**

 * 註解中有三個元素,一個是常量id,一個是sheel,一個是shareshare有默認值。

 * @author Administrator

 *

 */

@Retention(RetentionPolicy.CLASS)

@Target({ElementType.TYPE, ElementType.METHOD})

@Documented

@Inherited

public @interface Fruit {

public final int count = 1;

public int sheel();

public String share() default "";

}

 

定義了註解,必然要去使用註解。對@Fruit類進行的使用:

@Fruit(sheel=1)

public class Apple {

 

}

 

因爲在編寫@Fruit時沒有給sheel默認值,所以在使用@Fruit必須要給此元素賦值。有默認值的,我們可以對其進行修改:

@Fruit(sheel=1,share="")

public class Apple {

 

}

 

注意:常量不可以進行修改。

 

使用註解最主要的部分在於對註解的處理,那麼就會涉及到註解處理器。從原理上講,註解處理器就是通過反射機制獲取被檢查方法上的註解信息,然後根據註解元素的值進行特定的處理。

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