標籤:col ted 基礎 except ide 語義 地方 reflect try
一、基礎知識
Java支援在源檔案中嵌入補充資訊,這類資訊稱為註解(中繼資料)。註解不會改變程式的行為,因此也不會改變程式的語義。
二、聲明
上述聲明表示註解。註解都只能包含方法聲明,不能為這些方法提供實現,而是由Java實現。所有的註解類型都自動擴充了Annotation介面,其指定了annotationType方法,該方法返回調用註解的對象。
在聲明了註解之後就可以用來註解聲明了。所有的聲明都可以有與之關聯的註解,甚至註解本身也可以被註解。使用註解時,需要為註解的成員提供值。
class Solution { @interface MyAnnotation { String str(); int val() default 0;//使用預設值 } @MyAnnotation(str = "printHello", val = 1) public static void print() { System.out.println("Hello"); }}View Code
三、指定保留原則
註解保留原則決定了在什麼位置丟棄註解。Java於java.lang.annotation.RetentionPolicy枚舉中定義了三種保留策咯:
- SOURCE策略僅在源檔案中保留註解而編譯期拋棄。
- CLASS策略在編譯時間將註解儲存至class檔案中但是Java虛擬機器不能得到這些註解。
- RUNTIME策略提供了永久的註解。
import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation { String str(); int val();}View Code
四、使用反射擷取註解
如果為註解指定RUNTIME保留原則,任何程式在啟動並執行時候都可以使用反射來查詢註解。反射時能夠在運行時擷取類相關資訊的特性。
import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.reflect.Method;@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation { String str(); int val();}class Solution { @MyAnnotation(str = "Annotation content", val = 0) public static void printAnnotation() { Solution ob = new Solution(); try { Class<?> c = ob.getClass(); Method method = c.getMethod("printAnnotation"); MyAnnotation anno = method.getAnnotation(MyAnnotation.class); System.out.println(anno); } catch (NoSuchMethodException exc) { System.out.println("Method does not exist"); } } public static void main(String[] args) { printAnnotation(); }}View Code
擷取所有註解。
import java.lang.annotation.Annotation;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.reflect.Method;@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotationA { String str();}@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotationB { int val();}@MyAnnotationA(str = "Class annotation content")@MyAnnotationB(val = 1)class Solution { @MyAnnotationA(str = "Method annotation content") @MyAnnotationB(val = 0) public static void printAnnotation() { Solution ob = new Solution(); try { Annotation[] annos = ob.getClass().getAnnotations(); for (Annotation a : annos) System.out.println(a); Method method = ob.getClass().getMethod("printAnnotation"); annos = method.getAnnotations(); for (Annotation a : annos) System.out.println(a); } catch (NoSuchMethodException exc) { System.out.println("Method does not exist"); } } public static void main(String[] args) { printAnnotation(); }}View Code
五、相關介面
getAnnotation方法和getAnnotations方法均由AnnotatedElement介面定義,該介面支援註解反射。AnnotatedElement介面此外還定義了如下方法:
- getDeclaredAnnotations方法返回調用對象中存在的所有非繼承註解。
- isAnnotationPresent方法返回註解與對象是否關聯。
六、標記註解
標記註解是特殊類型的註解,其中不包含成員。標記註解的唯一目的就是標記聲明,確定標記註解是否存在的最好方式是使用isAnnotationPresent方法。
import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.reflect.Method;@Retention(RetentionPolicy.RUNTIME)@interface Marker {}class Solution { @Marker public static void printAnnotation() { Solution ob = new Solution(); try { Class<?> c = ob.getClass(); Method method = c.getMethod("printAnnotation"); System.out.println(method.isAnnotationPresent(Marker.class)); } catch (NoSuchMethodException exc) { System.out.println("Method does not exist"); } } public static void main(String[] args) { printAnnotation(); }}View Code
七、單成員註解
單成員註解通常只包含一個成員,允許使用縮寫形式指定成員值。該成員名稱必須是value,若包含其他成員則必須有預設值。
import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)@interface Single { String value(); int i() default 0;}class Solution { @Single("printHello") public static void print() { System.out.println("Hello"); }}View Code
八、內建註解
- Retention指定保留原則,只能註解其他註解。
- Documented是標記介面,通知其他工具註解將被文檔化,只能註解其他註解。
- Target指定可以應用註解的宣告類型,只能註解其他註解。可同時指定多個值。
- Inherited是標記註解,指明超類註解可被子類繼承,只能註解其他註解。
- Override是標記註解,指明必須重寫超類中的方法,只能註解方法。
- Deprecated是標記註解,指明聲明是過時的,已被新的形式取代。
- FunctionalInterface指明介面是函數式介面。函數式介面僅包含一個由lambda運算式所使用的抽象方法。
- SafeVarargs是標記註解,指明沒有發生與可變長度參數相關的不安全動作,只能用於方法和建構函式。
- SuppressWarnings指明抑制編譯器可能會報告的警告,使用字串表示警告名稱。
九、類型註解
最早的註解只能應用於聲明,但是現在已經能應用於使用類型的大多數地方。擴充後的這種註解稱為類型註解。類型註解允許工具對代碼執行額外檢查,從而協助避免錯誤。
import java.lang.annotation.ElementType;import java.lang.annotation.Target;@Target(ElementType.CONSTRUCTOR)@interface ConstructorAnno {}@Target(ElementType.TYPE_USE)@interface TypeAnno {}@Target(ElementType.TYPE_PARAMETER)@interface ParameterAnno {}@Target(ElementType.FIELD)@interface FieldAnno {}class Solution<@ParameterAnno T> { @FieldAnno @TypeAnno private T data; @ConstructorAnno Solution(@TypeAnno T data) { this.data = data; }}View Code
Java筆記:註解