深入annotation

接下來繼續介紹註解的生命週期和作用域。

@Target

上一節定義的所有註解中,可以在任意的位置上使用,比如類,方法,屬性等。如果需要指定其使用範圍的話就必須使用@Target註解,定義如下:

 

其中@Target的取值是ElementType類型,支持的取值如下:

 

代碼示例:定義註解,類型爲TYPE,只能在類上使用

import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Target(ElementType.TYPE)
@Retention(value= RetentionPolicy.RUNTIME)
public @interface MyTargetAnnotation {
    public String key() default "KSH";

}

此時在SimpleBean類和方法中使用此註解:

@MyTargetAnnotation()
public class SimpleBean {
    @MyTargetAnnotation()
    public String toString(){return "hello world!";}

}

可以看到,將MyTargetAnnotation註解作用到方法時會提示語法錯誤。

 

如果希望可以同時在類和方法中使用的話就需要設置多個範圍:

代碼示例:定義註解,類型爲TYPE和METHOD,只能在類和方法上使用

import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Target({ElementType.TYPE,ElementType.METHOD})//放到數組中
@Retention(value= RetentionPolicy.RUNTIME)
public @interface MyTargetAnnotation {
    public String key() default "KSH";

}

 

 

@Documented

可以作用到任何的註解上,所有的註解默認情況下都是使用@Documented進行註釋的,而且在生成javadoc的時候可以通過@Documented設置一些說明信息。

代碼示例:

import java.lang.annotation.Documented;


@Documented
@interface MyDocumentAnnotation {
    public String key() default "KSH";
    public String value() default "china";
}

@MyDocumentAnnotation(key="test",value="java")
public class SimpleBeanDocumented {
    @MyDocumentAnnotation(key="test",value="java")
    public String toString(){return "hello world!";}
}

執行javadoc命令可以生成文檔

 

 

 

@Inherited

表示一個註解是否可以被繼承下來。

代碼示例:定義一個可以被繼承的註解

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Documented
@Inherited
@Retention(value= RetentionPolicy.RUNTIME)
public @interface MyInheritedAnnotation {
    public String name();

}

代碼示例:定義一個父類,使用MyInheritedAnnotation 註解

@MyInheritedAnnotation(name="KSH")
public class Peple {

}

代碼示例:定義一個子類

public class Student  extends Peple{

}

代碼示例:通過反射機制,從子類獲取註解信息

import java.lang.annotation.Annotation;

public class ReflectInheritedDemo {
    public static void main(String [] args) throws ClassNotFoundException {
        Class<?> c = null;
        c = Class.forName("Chapter15.Student");
        Annotation ann[] = c.getAnnotations();//獲取所以的註解
        for(Annotation a:ann){
            System.out.println(a);
        }

        //獲取註解設置的內容
        if(c.isAnnotationPresent(MyInheritedAnnotation.class)){
            MyInheritedAnnotation mda = null;
            mda = c.getAnnotation(MyInheritedAnnotation.class);
            String name = mda.name();//取出name的內容
            System.out.println("name = "+name);
        }
    }
}

 

反射與註解

一個Annotation要是想變得有意義,必須結合反射機制取得Annotation中設置的全部內容。在Class類中有以下機制與Annotation操作有關的方法:

序號

方法

描述

1

public <A extends Annotation> A getAnnotation(Class<A> annotationClass)

如果一個元素存在註解,則取得註解

2

public Annotation[] getAnnotations()

返回元素上的所有註解

3

public Annotation[] getDeclaredAnnotations()

返回直接存在元素上的所有註解

4

public boolean isAnnotation()

判斷元素是否表示一個註解

5

public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

判斷一個元素上是否存在註解

 

代碼示例:

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

class SimpleBeanOne {
    @Deprecated
    @Override
    @SuppressWarnings("unchecked")
    public String toString(){return "hello java";}
}

public class ReflectDemo01{
    public static void main(String [] args) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> c = null;
        c = Class.forName("Chapter15.SimpleBeanOne");
        Method toM = c.getMethod("toString");//找到toString()方法
        Annotation ann[] = toM.getAnnotations();//獲取所有的註解
        for (Annotation a:ann) {
            System.out.println(a);
        }
    }
}

 

因爲只有Deprecated註解的定義範圍是RUNTIME,所以以上代碼通過反射只能取得一個註解。

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