要深入學習註解,我們必須能定義自己的註解,並且使用註解,在定義自己的註解之前,我們必須要了解Java為我們提供的元註解和相關定義註解的語法。
-------------------------------------------------- ------------------------------
元註解:
元註解的功能就是負責註解其他註解。 Java5.0定義了4個標準的meta-annotation類型,它們被用來提供對其它annotation類型作說明。 Java5.0定義的元註解:
1.@Target,
2.@Retention,
3.@Documented,
4.@Inherited
這些類型和它們所支援的類別在java.lang.annotation套件中可以找到。下面我們來看看每個元註解的作用和對應分參數的使用說明。
-------------------------------------------------- ------------------------------
@Target:
@Target說明了Annotation所修飾的物件範圍:Annotation可用於packages、types(類別、介面、枚舉、Annotation類型)、類型成員(方法、建構方法、成員變數、枚舉值)、方法參數和本地變數(如循環變數、catch參數)。在Annotation類型的聲明中使用了target可更加明晰其修飾的目標。
作用:用來描述註解的使用範圍(即:被描述的註解可以用在什麼地方)
取值(ElementType)有:
1.CONSTRUCTOR:用於描述建構器2.FIELD:用於描述域3.LOCAL_VARIABLE:用於描述局部變數4.METHOD:用於描述方法5.PACKAGE:用於描述套件6.PARAMETER:用於描述參數7.TYPE:用於描述類別、介面(包括註解類型) 或enum聲明
使用實例:
@Target(ElementType.FIELD)
public @interface NoDBColumn {
}
-------------------------------------------------- ------------------------------
@Retention:
@Retention定義了該Annotation被保留的時間長短:某些Annotation只會出現在原始碼中,而被編譯器丟棄;而另一些卻被編譯在class檔案中;編譯在class檔案中的Annotation可能會被虛擬機器忽略,而另一些在class被裝載時將被讀取(請注意並不影響class的執行,因為Annotation與class在使用上是被分離的)。使用這個meta-Annotation可以對Annotation的「生命週期」限制。
作用:表示需要在什麼層級保存該註釋訊息,用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效)
取值(RetentionPoicy)有:
1.SOURCE:在來源檔案中有效(即原始檔案保留)
2.CLASS:在class檔案中有效(即class保留)
3.RUNTIME:在運行時有效(即運行時保留)
Retention meta-annotation類型有唯一的value作為成員,它的取值來自java.lang.annotation.RetentionPolicy的枚舉類型值。具體實例如下:
-------------------------------------------------- ------------------------------
@Documented:
@Documented用來描述其它類型的annotation應該被作為被標註的程式成員的公共API,因此可以被例如javadoc此類的工具文檔化。 Documented是一個標記註解,沒有成員。
@Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類別。
注意:@Inherited annotation類型是被標註過的class的子類別所繼承。類別並不會從它所實作的介面繼承annotation,方法並沒有從它所重載的方法繼承annotation。
當@Inherited annotation類型標註的annotation的Retention是RetentionPolicy.RUNTIME,則反射API增強了這種繼承性。如果我們使用java.lang.reflect去查詢一個@Inherited annotation類型的annotation時,反射程式碼檢查將展開工作:檢查class和其父類,直到發現指定的annotation類型被發現,或到達類別繼承結構的頂層。
實例代碼:
-------------------------------------------------- ------------------------------
自訂註解:
使用@interface自訂註解時,自動繼承了java.lang.annotation.Annotation接口,由編譯程式自動完成其他細節。在定義註解時,不能繼承其他的註解或介面。 @interface用來宣告一個註解,其中的每一個方法實際上是聲明了一個配置參數。方法的名稱就是參數的名稱,回傳值型別就是參數的型別(傳回值型別只能是基本型別、Class、String、enum)。可以透過default來聲明參數的預設值。
定義註解格式:
public @interface 註解名稱{定義體}
註解參數的可支援資料型態:
1.所有基本資料型態(int,float,boolean,byte,double,char,long,short)
2.String類型3.Class類型4.enum類型5.Annotation類型6.以上所有類型的陣列
Annotation類型裡面的參數該怎麼設定:
第一,只能用public或預設(default)這兩個存取權修飾.例如,String value();這裡把方法設為defaul預設型別;
第二,參數成員只能用基本型別byte,short,char,int,long,float,double,boolean八種基本資料型別和String,Enum,Class,annotations等資料型別,以及這一些型別的陣列.例如,String value();這裡的參數成員就為String;
第三,如果只有一個參數成員,最好把參數名稱設為"value",後加小括號.例:下面的例子FruitName註解就只有一個參數成員。
簡單的自訂註解和使用註解實例:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 水果名稱註解
* @author peida
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
String value() default "";
}
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 水果顏色註解
* @author peida
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {
/**
* 顏色枚舉
* @author peida
*
*/
public enum Color{ BULE,RED,GREEN};
/**
* 顏色屬性
* @return
*/
Color fruitColor() default Color.GREEN;
}
import annotation.FruitColor.Color;
public class Apple {
@FruitName("Apple")
private String appleName;
@FruitColor(fruitColor=Color.RED)
private String appleColor;
public void setAppleColor(String appleColor) {
this.appleColor = appleColor;
}
public String getAppleColor() {
return appleColor;
}
public void setAppleName(String appleName) {
this.appleName = appleName;
}
public String getAppleName() {
return appleName;
}
public void displayName(){
System.out.println("水果的名字是:蘋果");
}
}