Annotation
通過使用Annotation,開發人員可以在不改變原有邏輯的情況下,在源文件中嵌入一些補充信息,以便于檢測錯誤,抑制警告等。Annotation不能運行,它只有成員變量,沒有成員方法。
1、定義Annotation
定義一個新的Annotation類型,類似于定義一個接口
public @interface Test {
}
使用時,將Annotation另起一行,放在所有修飾符之前,如:
@Test
public class MyClass {
}
Annotation只有成員變量,其成員變量在定義中以無形參的方法形式來聲明,其方法名定義了該成員變量的名字,返回值定義了該成員變量的類型。Annotation中的變量可以使用default關鍵字指定默認值。如:
public @interface MyTag {
String name() default "小明";
int age() default 18;
}
無默認值時,帶成員變量的Annotation使用時,必須為成員變量指定值;有默認值時可以不指定。如:
//無默認值時
public class MyClass {
@MyTag(name = "小明", age = 30)
public void info() {
}
}
//有默認值時
public class MyClass {
@MyTag
public void info() {
}
}
Annotation可分為兩類:
標記Annotation:沒有成員變量,僅用自身提供信息。如:@Override
元數據Annotation:含成員變量
2、元注解
注解的注解,用來修飾Annotation。有四個:
@Retention
@Target
@Documented
@Inherited
1)、@Retention
@Retention用于指定Annotation可以保留多長時間。
@Retention包含一個名為“value”的成員變量,該value成員變量是RetentionPolicy枚舉類型。使用@Retention時,必須為其value指定值。value成員變量的值只能是如下3個:
RetentionPolicy.SOURCE:Annotation只保留在源代碼中,編譯器編譯時,直接丟棄這種Annotation。(此時注解用于注釋)
RetentionPolicy.CLASS:編譯器把Annotation記錄在class文件中。當運行Java程序時,JVM中不再保留該Annotation。
RetentionPolicy.RUNTIME:編譯器把Annotation記錄在class文件中。當運行Java程序時,JVM會
保留該Annotation,程序可以通過反射獲取該Annotation的信息。
例如:
//name=value形式
//@Retention(value=RetentionPolicy.RUNTIME)
//直接指定
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTag{
String name() default "小明";
}
2)、@Target
@Target指定Annotation用于修飾哪些程序元素。@Target也包含一個名為”value“的成員變量,該value成員變量類型為ElementType[ ],ElementType為枚舉類型,值有如下幾個:
ElementType.TYPE:能修飾類、接口或枚舉類型
ElementType.FIELD:能修飾成員變量
ElementType.METHOD:能修飾方法
ElementType.PARAMETER:能修飾參數
ElementType.CONSTRUCTOR:能修飾構造器
ElementType.LOCAL_VARIABLE:能修飾局部變量
ElementType.ANNOTATION_TYPE:能修飾注解
ElementType.PACKAGE:能修飾包
例如:
//表示AnnTest可以修飾成員變量和方法
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface AnnTest {
String name() default "sunchp";
}
3)、@Documented
如果定義注解A時,使用了@Documented修飾定義,則在用javadoc命令生成API文檔后,所有使用注解A修飾的程序元素,將會包含注解A的說明。
例如:
@Documented
public @interface Testable {
}
public class Test {
@Testable
public void info() {
}
}
4)、@Inherited
@Inherited指定Annotation具有繼承性。
例如::
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyTag{
}
package com.demo2;
@MyTag
public class Base {
}
package com.demo2;
//SubClass只是繼承了Base類
//并未直接使用@MyTag注解修飾
public class SubClass extends Base {
public static void main(String[] args) {
System.out.println(SubClass.class.isAnnotationPresent(MyTag.class));
}
}
示例中Base使用@MyTag修飾,SubClass繼承Base,而且沒有直接使用@MyTag修飾,但是因為MyTag定義時,使用了@Inherited修飾,具有了繼承性,所以運行結果為true。
如果MyTag注解沒有被@Inherited修飾,則運行結果為:false。
3、常用Annotation
JDK默認提供了如下幾個基本Annotation:
1)、@Override
限定重寫父類方法。對于子類中被@Override 修飾的方法,如果存在對應的被重寫的父類方法,則正確;如果不存在,則報錯。@Override 只能作用于方法,不能作用于其他程序元素。
2)、@Deprecated
用于表示某個程序元素(類、方法等)已過時。如果使用被@Deprecated修飾的類或方法等,編譯器會發出警告。
3)、@SuppressWarning
抑制編譯器警告。指示被@SuppressWarning修飾的程序元素(以及該程序元素中的所有子元素,例如類以及該類中的方法.....)取消顯示指定的編譯器警告。例如,常見的@SuppressWarning(value="unchecked")
4)、@SafeVarargs
@SafeVarargs是JDK 7 專門為抑制“堆污染”警告提供的。