天天看點

猿來繪Java-44-自定義注解和元注解

自定義注解

定義新的 Annotation 類型使用 @interface 關鍵字,自定義注解是,可以參照Java中現有的注解,例如:@SuppressWarnings

自定義注解自動繼承了java.lang.annotation.Annotation接口

Annotation 的成員變量在 Annotation 定義中以無參數方法的形式來聲明。 其方法名和傳回值定義了該成員的名字和類型。 我們稱為配置參數。 類型隻能是八種基本資料類型、 String類型、 Class類型、 enum類型、 Annotation類型、以上所有類型的數組。

可以在定義 Annotation 的成員變量時為其指定初始值, 指定成員變量的初始值可使用 default 關鍵字

如果隻有一個參數成員, 建議使用參數名為value

如果定義的注解含有配置參數, 那麼使用時必須指定參數值, 除非它有預設值。 格式是“參數名 = 參數值” , 如果隻有一個參數成員, 且名稱為value,可以省略“value=”

沒有成員定義的 Annotation 稱為标記; 包含成員變量的 Annotation 稱為中繼資料 Annotation

注意: 自定義注解必須配上注解的資訊處理流程才有意義。

package com.ylaihui.annotations;

public @interface MyAnnotations {
    String[]  value() default "myanno";
}
           
//MyAnnotationTest.java
package com.ylaihui.annotations;

//@MyAnnotations("myanno")
@MyAnnotations
interface Info{
    public void show();
}

public class MyAnnotationTest {
    public static void main(String[] args) {

    }
}
           

4種元注解的使用

比如新購買的華為手機,有一本說明書,說明書中的前一頁有一段說明,是對說明書的說明。

 類比元注解,就是對現有注解的注解,對現有的注解的解釋說明。

JDK5.0提供了4個标準的meta-annotation類型, 分别是:

Retention

Target

Documented

Inherited

Retention

Retention:指定所修飾的 Annotation 的生命周期:SOURCE\CLASS(預設行為)\RUNTIME 隻有聲明為RUNTIME生命周期的注解,才能通過反射擷取。

SOURCE: Annotations are to be discarded by the compiler. 編譯後的class檔案不會有注解資訊

CLASS: Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time. class檔案有注解資訊,但是運作時無法得到注解資訊

RUNTIME: Annotations are to be recorded in the class file by the compiler and retained by the VM at run time,運作時可以擷取注解資訊,反射的時候用到

代碼示例:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
           

Target

@Target: 用于修飾 Annotation 定義, 用于指定被修飾的 Annotation 能用于修飾哪些程式元素。 @Target 也包含一個名為 value 的成員變量。

Target:用于指定所修飾的 Annotation 能用于修飾哪些程式元素

用法舉例

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
...
...
...
           

注解 SuppressWarnings 上面用Target修飾, 表示 SuppressWarnings 可以修飾 類型、屬性、方法、參數、構造器、局部變量, 如果 某個注解聲明為 @Target({TYPE}), 那麼隻可以修飾類型,不可以修飾屬性方法等

Documented

Documented:表示所修飾的注解在被javadoc解析時,保留下來。

@Documented: 用于指定被該元 Annotation 修飾的 Annotation 類将被javadoc 工具提取成文檔。 預設情況下, javadoc是不包括注解的。

定義為Documented的注解必須設定Retention值為RUNTIME。

用法舉例:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
           

Inherited

@Inherited: 被它修飾的 Annotation 将具有繼承性。如果某個類使用了被@Inherited 修飾的 Annotation, 則其子類将自動具有該注解。

比如:如果把标有@Inherited注解的自定義的注解标注在類級别上,子類則可以繼承父類類級别的注解,實際應用中,使用較少

Inherited:被它修飾的 Annotation 将具有繼承性。

某個類使用了注解 MyAnnotations,如果注解MyAnnotations有繼承性,也就是被 @Inherited修飾,那麼子類也繼承了父類的注解。

package com.ylaihui.annotation1;

import java.lang.annotation.*;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;

@Documented  // 所修飾的注解 MyAnnotation 在被javadoc解析時,保留下來
@Retention(RetentionPolicy.RUNTIME)  // MyAnnotation 注解資訊 保留到運作時,反射可以擷取注解資訊
@Target({TYPE, FIELD})   // MyAnnotation 注解可以修飾 類型、屬性
@Inherited  // 被它修飾 MyAnnotation 将具有繼承性,父類是 MyAnnotation,其子類也是 MyAnnotation
public @interface MyAnnotation {
    String[] value() default "ylaihui";
}
           
//AnnotationTest.java
package com.ylaihui.annotation1;

import java.lang.annotation.Annotation;

@MyAnnotation
class Person{
    @MyAnnotation
    String name;
    int age;

    // '@MyAnnotation' not applicable to method
    //@MyAnnotation
    public void show(){
        System.out.println();
    }
}

class Student extends Person{

}

public class AnnotationTest {
    public static void main(String[] args) {
        // 子類 Student 繼承了父類 Person的注解 MyAnnotation,
        // 因為 MyAnnotation 具有繼承性是聲明為 Inherited 的
        Annotation[] annotations = Student.class.getAnnotations();
        for (int i = 0; i < annotations.length; i++) {
            System.out.println(annotations[i]);
        }
    }
}