Java5增加了對MetaData
的支持,也就是Annotation
锋勺。
這些標記在編譯蚀瘸、類加載、運行時被讀取庶橱,并執(zhí)行相應的處理贮勃。通過使用注解,可以在不改變原邏輯的情況下悬包,在源文件中嵌入一些補充信息。
信息被存儲在Annotation
的"name-value"鍵值對中馍乙。
Annotation是一個接口布近,程序可以通過反射獲取指定程序元素的Annotation對象,通過該對象獲取注解的元數據丝格。
APT(Annotation Processing Tool)
一撑瞧、基本Annotation
Annotation必須使用工具處理,工具負責提取其中的元數據显蝌,還會根據元數據增加額外的功能预伺。
5個基本的Annotation(java.lang包下):
- @Deprecated
- @Override
- @SuppressWarning
- @SafeVarargs
- @FunctionalInterface
@Override
強制一個子類必須覆蓋父類的方法。
@Deprecated
表示某個程序元素已過時
@SuppressWarnings
抑制編譯器警告
@SuppressWarnings(value="unchecked")
public class Test{
public static void main(String[] args){
//不會有任何編譯警告
List<String> t = new ArrayList();
}
}
@SageVararges
List list = new ArrayList<Integer>();
//未經檢查的轉換曼尊,警告
list.add(20);
List<String> ls = list;
//引起運行時異常
System.out.println(ls.get(0));
這種情況稱為"堆污染"酬诀,把一個不帶泛型的變量賦給一個帶泛型的變量時,往往會發(fā)生堆污染骆撇。
抑制堆污染警告:
- @SafeVarargs
- @SuppressWarnings("unchecked")
- 編譯時使用-Xlint:varargs
@FunctionaInterface
JDK的元Annotation
除了java.lang
包下的5個基本注解瞒御。還有java.lang.annotation
報下提供的6個Meta Annotation
。五個用于修飾其他的Annotation
定義神郊。@Repeatable
用于定義Java8新增的重復注釋肴裙。
@Retention
用于修飾Annotation
定義,指定被修飾的注解可以保留多長時間涌乳。包含一個RetentionPolicy
類型的value成員變量蜻懦。value的值只能有3個:
- RetentionPolicy.CLASS:jvm不可獲取,默認值
- RetentionPolicy.RUNTIME:jvm可以獲取
- RetentionPolicy.SOURCE:只保留在源代碼中夕晓,編譯器直接丟棄這種
Annotation
如果要使用反射機制獲取注釋信息宛乃,則需要使用RetentionPolicy.RUNTIME
。
@Retention(value=RetentionPolicy.RUNTIME)
public @interface Testable(){}
@Retention(RetentionPolicy.RUNTIME)
public @interface Testable(){}
@Target
只能修飾Annotation
定義,用于指定被修飾的注解能用于修飾哪些程序單元烤惊,也包含一個名為value
的成員變量乔煞。取值:
- ElementType.ANNOTATION_TYPE
- ElementType.CONSTRUCTOR
- ElementType.FIELD
- ElementType.LOCAL_VARIABLE
- ElementType.METHOD
- ElementType.PACKAGE
- ElementType.TYPE
- ElementType.PARAMETER
@Documented
被該Annotation
標注的Annotation
類將被javadoc工具提取成文檔,如果定義Annotation
類是使用了該注解柒室,則所有使用Annotation
修飾的程序元素的api文檔中將會包含該Anntation
說明渡贾。
@Inherited
指定被它修飾的Annotation
將具有繼承性。
二雄右、自定義Annotation
public @interface Test{
}
還可以帶成員變量:
public @interface Test{
String name();
int age();
}
非常像定義了一個注釋接口空骚,這個注釋接口繼承了
Annotation
接口
也可以為成員變量指定默認值:
public @interface Test{
String name() default "HelloWorld";
int age() default 25;
}
提取Annotation信息
java.lang.reflect
包下新增了AnnotatedElement
接口,代表程序中可以接受注解的程序元素擂仍。該接口的實現類:
- Class
- Constructor
- Field
- Method
- Package
方法:
- <T extends Annotation> T getAnnotation(Class<T> annotationClass)
- Annotation[] getAnnotations()
- default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
- default <T extends Annotation> T[] getDeclaredAnnotation(Class<T> annotationClass)
- Annotation[] getDeclaredAnnotations()
- default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
- default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)