1. 程式人生 > >Java筆記:註解

Java筆記:註解

ram 獲取 val 永久 技術分享 function rri 名稱 class a

一、基礎知識

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筆記:註解