JVM5.0定義了4個標準的元註解:html
做用:用於描述註解的使用範圍
取值ElementType有:java
舉例:api
@Target(ElementType.TYPE) public @interface Table { /** * 數據表名稱註解,默認值爲類名稱 * @return */ public String tableName() default "className"; } @Target(ElementType.FIELD) public @interface NoDBColumn { }
註解Table能夠用於註解類、接口(包括註解類型)或enum聲明,而註解NoDBColumn僅用於註解類的成員變量。數組
做用:用於描述註解的生命週期
取值RetentionPolicy有:oracle
舉例:app
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { public String name() default "fieldName"; public String setFuncName() default "setField"; public String getFuncName() default "getField"; public boolean defaultDBValue() default false; }
Column註解的的RetentionPolicy的屬性值是RUNTIME,這樣註解處理器能夠經過反射,獲取到該註解的屬性值,從而去作一些運行時的邏輯處理ide
做用:用於描述其它類型的annotation應該被做爲被標註的程序成員的公共API,所以能夠被例如javadoc此類的工具文檔化。Documented是一個標記註解,沒有成員。工具
舉例:ui
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Column { public String name() default "fieldName"; public String setFuncName() default "setField"; public String getFuncName() default "getField"; public boolean defaultDBValue() default false; }
@Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。若是一個使用了Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。this
注意:Inherited annotation類型是被標註過的class的子類所繼承。類並不從它所實現的接口繼承annotation,方法並不從它所重載的方法繼承annotation。
當Inherited annotation類型標註的annotation的Retention是RetentionPolicy.RUNTIME,則反射API加強了這種繼承性。若是咱們使用java.lang.reflect去查詢一個Inherited annotation類型的annotation時,反射代碼檢查將展開工做:檢查class和其父類,直到發現指定的annotation類型被發現,或者到達類繼承結構的頂層。
實例代碼:
@Inherited public @interface Greeting { public enum FontColor{ BULE,RED,GREEN}; String name(); FontColor fontColor() default FontColor.GREEN; }
定義註解格式:
public @interface 註解名(定義體)
註解參數的可支持數據類型:
自定義註解的定義和具體實現能夠見下一章節。
建立註解處理器,利用反射對註解加以處理。
AnnotatedElement 接口是全部程序元素(Class、Method和Constructor)的父接口,關於AnnotatedElement點詳細信息能夠參考
JavaDoc:Interface AnnotatedElement。
因此程序經過反射獲取了某個類的AnnotatedElement對象以後,程序就能夠調用該對象的以下四個個方法來訪問Annotation信息:
<T extends Annotation> T getAnnotation(Class<T> annotationClass):
返回改程序元素上存在的、指定類型的註解,若是該類型註解不存在,則返回null。
方法2:Annotation[] getAnnotations():返回該程序元素上存在的全部註解。
方法3:boolean is AnnotationPresent(Class annotationClass):判斷該程序元素上是否包含指定類型的註解,存在則返回true,不然返回false.
方法4:Annotation[] getDeclaredAnnotations():返回直接存在於此元素上的全部註釋。與此接口中的其餘方法不一樣,該方法將忽略繼承的註釋。(若是沒有註釋直接存在於此元素上,則返回長度爲零的一個數組。)該方法的調用者能夠隨意修改返回的數組;這不會對其餘調用者返回的數組產生任何影響。
舉例:
1.FruitName
package annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitName { String value() default ""; }
2.FruitColor
package annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitColor { public enum Color{BlUE, RED, GREEN}; Color fruitColor() default Color.GREEN; }
3.FruitProvider
package annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitProvider { public int id() default -1; public String name() default ""; public String address() default ""; }
package annotation; import annotation.FruitColor.Color; public class Apple { @FruitName("Apple") private String appleName; @FruitColor(fruitColor=Color.RED) private String appleColor; @FruitProvider(id=1, name="紅富士集團", address="紅富士大廈") private String appleProvider; public String getAppleName() { return appleName; } public void setAppleName(String appleName) { this.appleName = appleName; } public String getAppleColor() { return appleColor; } public void setAppleColor(String appleColor) { this.appleColor = appleColor; } public String getAppleProvider() { return appleProvider; } public void setAppleProvider(String appleProvider) { this.appleProvider = appleProvider; } public void display(){ System.out.println("The fruit name is:" + appleName + ", its color is: " + appleColor + "."); } }
package annotation; import java.lang.reflect.Field; public class FruitInfoUtil { public static void getFruitInfo(Class<?> clazz){ String strFruitName= "水果名稱: "; String strFruitColor= "水果顏色: "; String strFruitProvider= "供應商信息: "; Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){ if (field.isAnnotationPresent(FruitName.class)){ FruitName fruitName = (FruitName)field.getAnnotation(FruitName.class); strFruitName += fruitName.value(); System.out.println(strFruitName); } if (field.isAnnotationPresent(FruitColor.class)){ FruitColor fruitColor = (FruitColor)field.getAnnotation(FruitColor.class); strFruitColor += fruitColor.fruitColor().toString(); System.out.println(strFruitColor); } if (field.isAnnotationPresent(FruitProvider.class)){ FruitProvider fruitProvider = (FruitProvider)field.getAnnotation(FruitProvider.class); strFruitProvider += " 供應商編號:" + fruitProvider.id() + " 供應商名稱:" + fruitProvider.name() + " 供應商地址:" + fruitProvider.address(); System.out.println(strFruitProvider); } } } }
執行結果:
水果名稱: Apple 水果顏色: RED 供應商信息: 供應商編號:1 供應商名稱:紅富士集團 供應商地址:紅富士大廈