概述
Annotation
可以標註 Java
語言中的類、方法、變量、參數和包等。
和 Javadoc 不同的是:Java
標註可以通過反射獲取標註內容。在編譯器生成類文件時,標註可以被嵌入到字節碼中。Java 虛擬機可以保留標註內容,在運行時可以獲取到標註內容 。
內置的註解
Java
定義了一套註解,共有 7 個,3 個在 java.lang
中,剩下 4 個在 java.lang.annotation
(元註解) 中。
@Override
,@Deprecated
,@SuppressWarnings
元註解
@Target
- 標記這個註解應該是哪種 Java
成員。
@Retention
- 標識這個註解怎麼保存,是隻在代碼中,還是編入class
文件中,或者是在運行時可以通過反射訪問。
@Documented
- 標記這些註解是否包含在用戶文檔中。
@Inherited
- 標記這個註解是繼承於哪個註解類(默認 註解並沒有繼承於任何子類)
Annotation結構
Annotation.java
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
ElementType.java
package java.lang.annotation;
public enum ElementType {
TYPE, /* 類、接口(包括註釋類型)或枚舉聲明 */
FIELD, /* 字段聲明(包括枚舉常量) */
METHOD, /* 方法聲明 */
PARAMETER, /* 參數聲明 */
CONSTRUCTOR, /* 構造方法聲明 */
LOCAL_VARIABLE, /* 局部變量聲明 */
ANNOTATION_TYPE, /* 註釋類型聲明 */
PACKAGE /* 包聲明 */
}
RetentionPolicy.java
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE, /* Annotation信息僅存在於編譯器處理期間,編譯器處理完之後就沒有該Annotation信息了 */
CLASS, /* 編譯器將Annotation存儲於類對應的.class文件中。默認行爲 */
RUNTIME /* 編譯器將Annotation存儲於class文件中,並且可由JVM讀入 */
}
獲取annotation
通過反射,拿到annotation
例如,
/**
* Annotation在反射函數中的使用示例
*/
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String[] value() default "unknown";
}
獲取
// 獲取該方法的MyAnnotation註解實例
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
// 獲取 myAnnotation的值,並打印出來
String[] values = myAnnotation.value();
Annotation
參數,如果方法是value
可以用直接傳值的方式,如果是其他方法名,使用name
= value
的格式
完整demo
import java.lang.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
import java.lang.reflect.Method;
/**
* Annotation在反射函數中的使用示例
*/
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String[] value() default "unknown";
}
/**
* Person類。它會使用MyAnnotation註解。
*/
class Person {
/**
* empty()方法同時被 "@Deprecated" 和 "@MyAnnotation(value={"a","b"})"所標註
* (01) @Deprecated,意味着empty()方法,不再被建議使用
* (02) @MyAnnotation, 意味着empty() 方法對應的MyAnnotation的value值是默認值"unknown"
*/
@MyAnnotation
@Deprecated
public void empty(){
System.out.println("\nempty");
}
/**
* sombody() 被 @MyAnnotation(value={"girl","boy"}) 所標註,
* @MyAnnotation(value={"girl","boy"}), 意味着MyAnnotation的value值是{"girl","boy"}
*/
@MyAnnotation(value={"girl","boy"})
public void somebody(String name, int age){
System.out.println("\nsomebody: "+name+", "+age);
}
}
public class AnnotationTest {
public static void main(String[] args) throws Exception {
// 新建Person
Person person = new Person();
// 獲取Person的Class實例
Class<Person> c = Person.class;
// 獲取 somebody() 方法的Method實例
Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});
// 執行該方法
mSomebody.invoke(person, new Object[]{"lily", 18});
iteratorAnnotations(mSomebody);
// 獲取 somebody() 方法的Method實例
Method mEmpty = c.getMethod("empty", new Class[]{});
// 執行該方法
mEmpty.invoke(person, new Object[]{});
iteratorAnnotations(mEmpty);
}
public static void iteratorAnnotations(Method method) {
// 判斷 somebody() 方法是否包含MyAnnotation註解
if(method.isAnnotationPresent(MyAnnotation.class)){
// 獲取該方法的MyAnnotation註解實例
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
// 獲取 myAnnotation的值,並打印出來
String[] values = myAnnotation.value();
for (String str:values)
System.out.printf(str+", ");
System.out.println();
}
// 獲取方法上的所有註解,並打印出來
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations){
System.out.println(annotation);
}
}
}