1. 程式人生 > >JAVA註解Annotation

JAVA註解Annotation

深入理解java java註解 annotation 註解處理器 annotatedelement

從 JDK 5.0 開始, Java 增加了對元數據(MetaData) 的支持, 也就是 Annotation(註解)
Annotation 其實就是代碼裏的特殊標記, 這些標記可以在編譯, 類加載, 運行時被讀取, 並執行相應的處理. 通過使用 Annotation, 程序員可以在不改變原有邏輯的情況下, 在源文件中嵌入一些補充信息.
Annotation 可以像修飾符一樣被使用, 可用於修飾包,類, 構造器, 方法, 成員變量, 參數, 局部變量的聲明, 這些信息被保存在 Annotation 的 “name=value” 對中.
Annotation 能被用來為程序元素(類, 方法, 成員變量等) 設置元數據


三個基本的 Annotation:
@Override: 限定重寫父類方法, 該註釋只能用於方法
@Deprecated: 用於表示某個程序元素(類, 方法等)已過時
@SuppressWarnings: 抑制編譯器警告


JDK5.0提供了專門在註解上的註解類型,分別是:
1.Retention
2.Target
3.Documented
4.Inherited

@Retention: 只能用於修飾一個 Annotation 定義, 用於指定該 Annotation 可以保留多長時間, @Rentention 包含一個 RetentionPolicy 類型的成員變量, 使用 @Rentention 時必須為該 value 成員變量指定值:

RetentionPolicy.SOURCE: 編譯器直接丟棄這種策略的註釋
RetentionPolicy.CLASS: 編譯器將把註釋記錄在 class 文件中. 當運行 Java 程序時, JVM 不會保留註 解。 這是默認值
RetentionPolicy.RUNTIME:編譯器將把註釋記錄在 class 文件中. 當運行 Java 程序時, JVM 會保留註釋. 程序可以通過反射獲取該註釋
@Target: 用於修飾 Annotation 定義, 用於指定被修飾的 Annotation 能用於修飾哪些程序元素. @Target 也包含一個名為 value 的成員變量.
@Documented:
用於指定被該元 Annotation 修飾的 Annotation 類將被 javadoc 工具提取成文檔.
定義為Documented的註解必須設置Retention值為RUNTIME。
@Inherited: 被它修飾的 Annotation 將具有繼承性.如果某個類使用了被 @Inherited 修飾的 Annotation, 則其子類將自動具有該註解
實際應用中,使用較少


註解處理器類庫(java.lang.reflect.AnnotatedElement):

  Java使用Annotation接口來代表程序元素前面的註解,該接口是所有Annotation類型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,該接口代表程序中可以接受註解的程序元素,該接口主要有如下幾個實現類:

  Class:類定義
  Constructor:構造器定義
  Field:累的成員變量定義
  Method:類的方法定義
  Package:類的包定義

  java.lang.reflect 包下主要包含一些實現反射功能的工具類,實際上,java.lang.reflect 包所有提供的反射API擴充了讀取運行時Annotation信息的能力。當一個Annotation類型被定義為運行時的Annotation後,該註解才能是運行時可見,當class文件被裝載時被保存在class文件中的Annotation才會被虛擬機讀取。
  AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通過反射獲取了某個類的AnnotatedElement對象之後,程序就可以調用該對象的如下四個個方法來訪問Annotation信息:

  方法1:<T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定類型的註解,如果該類型註解不存在,則返回null。
  方法2:Annotation[] getAnnotations():返回該程序元素上存在的所有註解。
  方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判斷該程序元素上是否包含指定類型的註解,存在則返回true,否則返回false.
  方法4:Annotation[] getDeclaredAnnotations():返回直接存在於此元素上的所有註釋。與此接口中的其他方法不同,該方法將忽略繼承的註釋。(如果沒有註釋直接存在於此元素上,則返回長度為零的一個數組。)該方法的調用者可以隨意修改返回的數組;這不會對其他調用者返回的數組產生任何影響。

  一個簡單的註解處理器:  

/***********註解聲明***************//**
 * 水果名稱註解
 * @author yang
 * [email protected](ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documentedpublic @interface FruitName {
    String value() default "";
}/**
 * 水果顏色註解
 * @author yang
 * [email protected](ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documentedpublic @interface FruitColor {    /**
     * 顏色枚舉
     * @author peida
     *     */
    public enum Color{ BULE,RED,GREEN};    
    /**
     * 顏色屬性
     * @return
     */
    Color fruitColor() default Color.GREEN;

}/**
 * 水果供應者註解
 * @author yang
 * [email protected](ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documentedpublic @interface FruitProvider {    /**
     * 供應商編號
     * @return
     */
    public int id() default -1;    
    /**
     * 供應商名稱
     * @return
     */
    public String name() default "";    
    /**
     * 供應商地址
     * @return
     */
    public String address() default "";
}/***********註解使用***************/public class Apple {
    
    @FruitName("Apple")    private String appleName;
    
    @FruitColor(fruitColor=Color.RED)    private String appleColor;
    
    @FruitProvider(id=1,name="陜西紅富士集團",address="陜西省西安市延安路89號紅富士大廈")    private String appleProvider;    
    public void setAppleColor(String appleColor) {        this.appleColor = appleColor;
    }    public String getAppleColor() {        return appleColor;
    }    
    public void setAppleName(String appleName) {        this.appleName = appleName;
    }    public String getAppleName() {        return appleName;
    }    
    public void setAppleProvider(String appleProvider) {        this.appleProvider = appleProvider;
    }    public String getAppleProvider() {        return appleProvider;
    }    
    public void displayName(){
        System.out.println("水果的名字是:蘋果");
    }
}/***********註解處理器***************/
public class FruitInfoUtil {    
    public static void getFruitInfo(Class<?> clazz){
        String strFruitName=" 水果名稱:";
        String strFruitColor=" 水果顏色:";
        String strFruitProvicer="供應商信息:";
        
        Field[] fields = clazz.getDeclaredFields();        
        for(Field field :fields){            if(field.isAnnotationPresent(FruitName.class)){
                FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
                strFruitName=strFruitName+fruitName.value();
                System.out.println(strFruitName);
            }            else if(field.isAnnotationPresent(FruitColor.class)){
                FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);
                strFruitColor=strFruitColor+fruitColor.fruitColor().toString();
                System.out.println(strFruitColor);
            }            else if(field.isAnnotationPresent(FruitProvider.class)){
                FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);
                strFruitProvicer=" 供應商編號:"+fruitProvider.id()+" 供應商名稱:"+fruitProvider.name()+" 供應商地址:"+fruitProvider.address();
                System.out.println(strFruitProvicer);
            }
        }
    }
}
/***********輸出結果***************/public class FruitRun {   
 /**
  * @param args    
  */
  public static void main(String[] args) {
    FruitInfoUtil.getFruitInfo(Apple.class);
  }

}
====================================
 水果名稱:Apple
 水果顏色:RED
 供應商編號:1 供應商名稱:陜西紅富士集團 供應商地址:陜西省西安市延安路89號紅富士大廈

Java註解的基礎知識點(見下面導圖)基本都過了一遍,下一篇我們通過設計一個基於註解的簡單的ORM框架,來綜合應用和進一步加深對註解的各個知識點的理解和運用。

技術分享

本文出自 “ciyo技術分享” 博客,請務必保留此出處http://ciyorecord.blog.51cto.com/6010867/1934218

JAVA註解Annotation