java新特性—Annotation
Annotation
一、概念
1、
Annontation是Java5開始引入的新特徵。中文名稱一般叫註解。
2、
它提供了一種安全的類似註釋的機制,用來將任何的資訊或元資料(metadata)與程式元素(類、方法、成員變數等)進行關聯。
3、
是為程式的元素(類、方法、成員變數)加上直觀明瞭的說明,這些說明資訊是與程式的業務邏輯無關,並且是供指定的工具或框架使用的。
4、
Annontation像一種修飾符一樣,應用於包、型別、構造方法、方法、成員變數、引數及本地變數的宣告語句中。
二、原理
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型別也可以如介面一般被實現或者繼承。
三丶應用
1、
annotation一般作為一種輔助途徑,應用在【軟體框架或工具】中,在這些工具類中根據不同的 annontation註解資訊採取不同的處理過程或改變相應程式元素(類、方法及成員變數等)的行為。
例如:Junit、Struts、Spring等流行工具框架中均廣泛使用了annontion。使程式碼的靈活性大提高。
四丶【@Override】、【@Deprecated】、【@SuppressWarnings】
1、@Override:
在方法覆寫(重寫)的時候使用。
|- java.lang.Override
是一個marker annotation
型別,它被用作標註方法。它說明了【被標註的方法重寫了父類的方法】
,起到了斷言的作用。如果我們使用了這種annotation在一個沒有重寫父類方法的方法時,java編譯器將以一個編譯錯誤來警示。
|- 這個annotaton常常在我們試圖重寫父類方法而確又寫錯了方法名時加一個保障性的校驗過程。
2、@Deprecated
表示一個類和方法已經不再建議繼續使用了。
|- Deprecated也是一種marker annotation。當一個型別或者型別成員使用@Deprecated修飾的話,編譯器將不鼓勵使用這個被標註的程式元素。所以使用這種修飾具有一定的 “延續性”:如果我們在程式碼中通過繼承或者覆蓋的方式使用了這個過時的型別或者成員,雖然繼承或者覆蓋後的型別或者成員並不是被宣告為 @Deprecated,但編譯器仍然要報警。
|- 注意:
@Deprecated這個annotation型別和javadoc中的 @deprecated這個tag是有區別的:前者是java編譯器識別的,而後者是被javadoc工具所識別用來生成文件(包含程式成員為什麼已經過時、它應當如何被禁止或者替代的描述)。
3、@SuppressWarnings
表示壓制警告資訊。告訴Java編譯器關閉對類、方法及成員變數的警告。
|- 有時編譯時會提出一些警告,對於這些警告有的隱藏著Bug,有的是無法避免的,【對於某些不想看到的警告資訊,可以通過這個註解來遮蔽】
。
|- SuppressWarning不是一個marker annotation。它有一個型別為String[]的成員,這個成員的值為被禁止的警告名。對於javac編譯器來講,被-Xlint選項有效的警告名也同樣對@SuppressWarings有效,同時編譯器忽略掉無法識別的警告名。
|- annotation語法允許在@SuppressWarnings後跟括號,括號中是使用逗號分割的【name=value對】用於為annotation的成員賦值。
有這樣的程式碼如下:
@SuppressWarnings(value={"unchecked","fallthrough"})
public void lintTrap(){/*sloppy method body omitted*/}
在這個例子中SuppressWarnings annotation型別只定義了一個單一的成員,所以只有一個簡單的value={…}作為name=value對。又由於成員值是一個數組,故使用大括號來宣告陣列值。
注意:
我們可以在下面的情況中縮寫annotation
:當annotation只有單一成員,併成員命名為”value=”。這時可以省去”value=”。比如將上面的SuppressWarnings annotation進行縮寫。
程式碼:
@SuppressWarnings({"unchecked","fallthrough"})
如果SuppressWarnings所宣告的被禁止警告個數為一個時,可以省去大括號:
@SuppressWarnings("unchecked")
五丶自定義的Annotation
Annotation自定義的語法如下:
訪問控制權限 @interface Annotation 名稱()
public @interface MyAnnotation{}
這是一個簡單的內容為空沒有變數的Annotation。
而且在Annotation中可以定義若干個變數,接受設定。
===================================
在Annotation中定義變數。
public @interface MyAnnotation{
public String name();
public String info();
}
由於設定了引數,所以使用的時候就必須設定變數的內容。
在此使用Annotation的時候就必須設定兩個引數的內容。
@MyAnnotation(name="HELLO",info="WORLD")
====================================
可以通過default指定預設值
public @interface MyAnnotation{
public String name() default "Hello";
public String info() default "World";
}
這樣即使不指定變數的內容,程式也不會出現任何的錯誤。
@MyAnnotation
====================================
可以定義一個數組在Annotation中
public @interface MyAnnotation{
public String[] name();
}
變數name是以陣列的形式出現,所以設定的時候必須設定上一個陣列。
@MyAnnotation(name = {"Hello","World"})
=====================================
還可以通過列舉操作給一個Annotation的變數指定取值範圍
publilc enum Color{
RED,GREEN,BLUE
}
public @interface MyAnnotation{
public Color color();
}
使用的時候從Color中指定具體的型別。
@MyAnnotation(color = Color.RED)