Java註解(Annotation)筆記

概述

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);
        }
    }
}

參考資料

Java 註解(Annotation)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章