程式扎記: [ Java 文章收集 ] Java Reflection: Annotations

標籤

2013年5月30日 星期四

[ Java 文章收集 ] Java Reflection: Annotations

來源自 這裡
Preface:
使用 Java 反射的特性 (Reflection) 可以讓你在執行時獲取 Java 類別上面定義的 annotation, 底下將介紹如何取得 Java 類別, 方法與屬性上面定義的 annotation.

What are Java Annotations?
Annotation 是在 Java 5 以後增加的 feature, 它有點類似定義所謂的 meta data 到 Java 的代碼中. 如此你可以在 compile java 成 class 時知道一些額外的訊息 (如是否抑制 warning 訊息 etc) 或是在執行時期取出這些 annotations 作為判斷後續處理的依據. 底下是一個使用 annotation 的範例:
  1. @MyAnnotation(name="someName",  value = "Hello World")  
  2. public class TheClass {  
  3. }  
在上面的範例中, 我們在類別 TheClass上面標記了 annotation "MyAnnotation", 而此 annotation 是一個自訂義的 annotation, 你可以如下定義 annotation:
  1. @Retention(RetentionPolicy.RUNTIME)  
  2. @Target(ElementType.TYPE)  
  3.   
  4. public @interface MyAnnotation {  
  5.     public String name();  
  6.     public String value();  
  7. }  
在 annotation "MyAnnotation" 中我們又標記了下面兩個 annotation:
- @Retention(RetentionPolicy.RUNTIME)
It means that the annotation can be accessed via reflection at runtime. If you do not set this directive, the annotation will not be preserved at runtime, and thus not available via reflection.

- @Target(ElementType.TYPE) 
It means that the annotation can only be used ontop of types (classes and interfaces typically). You can also specify METHOD or FIELD, or you can leave the target out alltogether so the annotation can be used for both classes, methods and fields.

而更多有關 Java annotation 的說明可以參考 這裡

Class Annotations:
當你在類別上面定義了 annotation 且該 annotation 是 Runtime 可以 access 的, 則你可以如下從類別中取出它的 annotation:
  1. Class aClass = TheClass.class;  
  2. Annotation[] annotations = aClass.getAnnotations();  
  3.   
  4. for(Annotation annotation : annotations){  
  5.     if(annotation instanceof MyAnnotation){  
  6.         MyAnnotation myAnnotation = (MyAnnotation) annotation;  
  7.         System.out.println("name: " + myAnnotation.name());  
  8.         System.out.println("value: " + myAnnotation.value());  
  9.     }  
  10. }  
如果你要取出特定的 annotation 也可以參考下面的方法:
  1. Class aClass = TheClass.class;  
  2. Annotation annotation = aClass.getAnnotation(MyAnnotation.class);  
  3. if(annotation!=null)  
  4. {  
  5.     MyAnnotation myAnnotation = (MyAnnotation) annotation;  
  6.     System.out.println("name: " + myAnnotation.name());  
  7.        System.out.println("value: " + myAnnotation.value());  
  8. }  
Method Annotations:
如果你是要在方法上面使用 annotation, 則剛剛的 "MyAnnotation" 便不能使用, 因此我又定義一個使用在方法上的 annotation:
  1. package test.annotation;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. @Retention(RetentionPolicy.RUNTIME)  
  9. @Target(ElementType.METHOD)  
  10. public @interface MAnnotation {  
  11.     public String name();  
  12.     public String value();  
  13. }  
並在類別 TheClass 上面的方法 doSomething 標記 "MAnnotation":
  1. @MAnnotation(name="someName",  value = "Hello World")  
  2. public void doSomething(){}  
如此你便可以使用下面方法取出 doSomething 上面的所有 annotation:
  1. Method method = TheClass.class.getMethod("doSomething");  
  2. Annotation[] annotations = method.getDeclaredAnnotations();  
  3.   
  4. for (Annotation annotation : annotations) {  
  5.     if (annotation instanceof MAnnotation) {  
  6.         MAnnotation myAnnotation = (MAnnotation) annotation;  
  7.         System.out.println("name: " + myAnnotation.name());  
  8.         System.out.println("value: " + myAnnotation.value());  
  9.     }  
  10. }  
或者你可以如下取出特定的 annotation:
  1. Method method = TheClass.class.getMethod("doSomething");  
  2. Annotation annotation = method.getAnnotation(MAnnotation.class);  
  3. if(annotation!=null)  
  4. {  
  5.     MAnnotation mAnnotation = (MAnnotation) annotation;  
  6.     System.out.println("name: " + mAnnotation.name());  
  7.        System.out.println("value: " + mAnnotation.value());  
  8. }  
Parameter Annotations:
你也可以在方法上的參數使用 annotation, 首先定義使用的 annotation 如下:
  1. package test.annotation;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. @Retention(RetentionPolicy.RUNTIME)  
  9. @Target(ElementType.PARAMETER)  
  10. public @interface PAnnotation {  
  11.     public String name();  
  12.     public String value();  
  13. }  
接著可以在方法 doSomething 上的參數 p 標記 "PAnnotation":
  1. public void doSomething(  
  2.         @PAnnotation(name="aName", value="aValue"int p  
  3. ){}  
接著你可以參考下面方法取出方法所有參數與其對應的 annotation:
  1. Method method = TheClass.class.getMethod("doSomething"int.class);  
  2. Annotation[][] parameterAnnotations = method.getParameterAnnotations();  
  3. Class[] parameterTypes = method.getParameterTypes();  
  4.   
  5. int i=0;  
  6. for(Annotation[] annotations : parameterAnnotations){  
  7.   Class parameterType = parameterTypes[i++];  
  8.   
  9.   for(Annotation annotation : annotations){  
  10.     if(annotation instanceof PAnnotation){  
  11.         PAnnotation myAnnotation = (PAnnotation) annotation;  
  12.         System.out.println("param: " + parameterType.getName());  
  13.         System.out.println("name : " + myAnnotation.name());  
  14.         System.out.println("value: " + myAnnotation.value());  
  15.     }  
  16.   }  
  17. }  
Field Annotations:
最後同樣的在類別上面定義的屬性也可以進行標記, 首先定義使用的 annotation 如下:
  1. package test.annotation;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. @Retention(RetentionPolicy.RUNTIME)  
  9. @Target(ElementType.FIELD)  
  10. public @interface FAnnotation {  
  11.     public String name();  
  12.     public String value();  
  13. }  
並在類別 TheClass 上面的屬性 myField 標記如下:
  1. @FAnnotation(name="someName",  value = "Hello World")  
  2. public String myField = null;  
接著可以如下取出該屬性上的 annotation:
  1. Field field = TheClass.class.getField("myField");  
  2. Annotation[] annotations = field.getDeclaredAnnotations();  
  3.   
  4. for (Annotation annotation : annotations) {  
  5.     if (annotation instanceof FAnnotation) {  
  6.         FAnnotation myAnnotation = (FAnnotation) annotation;  
  7.         System.out.println("name: " + myAnnotation.name());  
  8.         System.out.println("value: " + myAnnotation.value());  
  9.     }  
  10. }  
或者如下取出特定的 annotation:
  1. Field field = TheClass.class.getField("myField");  
  2. Annotation annotation = field.getAnnotation(FAnnotation.class);  
  3. if(annotation!=null)  
  4. {  
  5.     FAnnotation mAnnotation = (FAnnotation) annotation;  
  6.     System.out.println("name: " + mAnnotation.name());  
  7.        System.out.println("value: " + mAnnotation.value());  
  8. }  
Supplement:
良葛格 > Java Essence > 標準小老鼠
良葛格 > Java Essence > 自訂小老鼠型態
良葛格 > Java Essence > 讀取小老鼠的心聲
良葛格 > Java Essence > 還有其它小老鼠
Java Annotation入門 (cleverpig's blog)
在5.0版之前的Java平台已經具有了一些ad hoc annotation機制。比如,使用transient修飾符來標識一個成員變量在序列化子系統中應被忽略。而@deprecated這個javadoc tag也是一個ad hoc annotation用來說明一個方法已過時。從Java5.0版發布以來,5.0平台提供了一個正式的annotation功能:允許開發者定義、使用自己的annoatation類型。此功能由一個定義annotation類型的語法和一個描述annotation聲明的語法,讀取annotaion的API,一個使用annotation修飾的class文件,一個annotation處理工具(apt)組成...

This message was edited 20 times. Last update was at 30/05/2013 16:12:08

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!