接下來繼續介紹註解的生命週期和作用域。
@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,所以以上代碼通過反射只能取得一個註解。