註解概述
註解即Annotation是JDK5.0開始引入的新技術。
作用:
- 註解不是程序本身,但是可以對程序作出解釋。這一點的功能類似於註釋(comment)。
- 註解可以被其他程序讀取,如編譯器。
格式: 註解 是以 “@註釋名” 的形式在程序中存在的,還可以添加一些參數。例如:@SuppressWarnings(value=“unchecked”)。
使用範圍:
註解可以附加在package、class、method、field等上面,這相當於給他們添加了額外的輔助信息。我們可以通過反射機制編程實現對這些元數據的訪問。
分類:
- 內置註解
- 元註解
- 自定義註解
內置註解
內置註解是註解的一種。我們遇到的 @Override、@Deprecated、@SuppressWarnings 都是內置註解。
當我們在進行方法的重寫的時候,會遇到方法的上一行是 “@Override”,@Override 就是一個內置註解,它是定義在java.lang.Override中的,該註解只適用於修飾方法,表明一個方法聲明打算重寫超類(父類)的另一個方法聲明。
在調用一個類的方法時,有時會遇到"@Deprecated",@Deprecated是定義java.lang.Deprecated 中的,該註解可以用於修飾方法、屬性、類,表示不鼓勵程序員使用這樣的元素,通常是因爲它很危險或者存在更好的選擇。對於由"@Deprecated"修飾的元素,java中是不建議使用的,但是是可以使用的。
@SuppressWarnings,定義在java.lang.SuppressWarnings中,用於一直編譯時的警告信息。但與上面的註解不同的是,需要添加一個參數纔可以正確使用該註解,這些參數是java定義好的,我們只要選擇性地去使用就行。如下:
@SuppressWarnings("all")
@SuppressWarnings("unchecked")
@SuppressWarnings(value={"unchecked","deprecation"})
元註解
元註解是註解的一個分類,它的作用是負責註解其他註解,java中定義了四個標準的meta-annotation類型,它們被用來提供對其他annotation類型作說明。
這些類型和它們所支持的類在java.lang.annotation包中可以找到。
分類:
- @Target:用於描述註解的使用範圍即被描述的註解可以用在什麼地方。
- @Retention:表示需要在什麼級別保存該註解信息,用於描述註解的生命週期。
- @Documented:說明該註解將被包含在javadoc中。
- @Inherited:說明子類可以繼承父類中的該註解。
@Target
@Target:用於描述註解的使用範圍即被描述的註解可以用在什麼地方。
@Target源碼:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
ElementType源碼:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
根據源碼可以知道,@Target註解的使用範圍:
名稱 | 使用範圍 |
---|---|
TYPE | 類,接口(包括註解類型)以及枚舉 |
FIELD | 字段(包括枚舉常量) |
METHOD | 方法 |
PARAMETER | 參數 |
CONSTRUCTOR | 構造方法 |
LOCAL_VARIABLE | 局部變量 |
ANNOTATION_TYPE | 註解類型 |
PACKAGE | 包 |
TYPE_PARAMETER(JDK1.8開始) | 類型參數 |
TYPE_USE(JDK1.8開始) | 類型的使用 |
@Retention
@Retention:表示需要在什麼級別保存該註解信息,用於描述註解的生命週期。
@Retention源碼:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
RetentionPolicy源碼:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
根據源碼可以知道 @Retention使用的生命週期有三個:
- SOURCE:註解將被編譯器丟棄
- CLASS:註解由編譯器記錄在類文件中,但虛擬機在運行時無需保留。 這是默認行爲。
- RUNTIME:註解由編譯器記錄在類文件中,並在運行時由VM保留,因此可以通過反射方式讀取它們。
上面的三個生命週期是 SOURCE < CLASS < RUNTIME.
@Documented
@Documented:說明該註解將被包含在javadoc中。
@Documented 源碼:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Inherited
@Inherited:說明子類可以繼承父類中的該註解。
@Inherited源碼:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
自定義註解
除了java給我們提供的內置註解之外,我們還可以自己定義註解,即自定義註解。
格式:
public @interface 註解名 {
定義內容
}
在使用 @interface 自定義註解時,會自動繼承java.lang.annotation.Annotation接口。
分析:
- @interface 用來聲明一個註解
- 定義的註解中的每一個方法實際上是聲明瞭一個配置參數
- 方法的名稱就是參數的名稱
- 返回值類型就是參數的類型,返回值類型只能是基本類型、Class、String、enum
- 可以通過default來聲明參數的默認值
- 如果只有一個參數成員,一般參數名爲value
- 註解元素必須要有值,在定義註解元素時,經常食用空字符串、0作爲默認值。
自定義註解舉例:
public class Test01 {
public static void main(String[] args) {
test();
}
@MyAnnotation("ll")
public static void test(){
System.out.println("This is my annotation");
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
String value(); // 只有一個參數成員時,一般參數名爲value
}
上述例子中,自定義註解的參數只有一個,所以將參數名命名爲value,且在寫 @MyAnnotation(“ll”) 註解的時候,可以將參數名省去即將"value="省略不寫,但是當註解中的參數大於等於兩個時,就必須加上參數名。如下:
public class Test01 {
public static void main(String[] args) {
test();
}
@MyAnnotation(value = "ll",num = 1)
public static void test(){
System.out.println("This is my annotation");
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
String value();
int num();
}
自定義註解中,默認值的使用:
public class Test01 {
public static void main(String[] args) {
test();
}
@MyAnnotation(value = "ll")
public static void test(){
System.out.println("This is my annotation");
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
String value();
int num() default 0;
}
當參數有默認值的時候,在寫註解時該參數可以傳遞參數也可以不傳遞參數。