二十七、JDK1.5新特性---Annotation

        上篇文章介紹了反射的一些基礎知識以及應用案例,本文將介紹jdk 1.5 出現的新特性——Annotation也就是我們所說的註解,即使用註釋的方式加入一些程序的信息。

註解相當於一種標記,在程序中加了註解就等於爲程序打上了某種標記,沒加,則等於沒有某種標記。

    Java.lang.annotation. Annotation 接口是所有的Annotation都必須實現的接口。下面我們將從系統的三個內建Annotation開始學習。

內建Annotation

      ♥ @Overrider :複寫的Annotation

        ♥ @Deprecated : 不贊成使用的Annotation,通常表示過時

        ♥ @SuppressWarnings :壓制安全警告的Annotation

Overrider作用與用法

        表示當前方法是在複寫父類的方法,當我們複寫父類的一個方法時可以在方法上面寫上@ Overrider,其作用是驗證該方法是否拼寫錯誤,如果編寫錯誤則編譯失敗。從而提高了程序的安全性

Deprecated作用與用法

    通常表示當前方法不建議使用或者是已經因爲某種原因已經過時,現在有更好的方法,從而保證程序的健壯性

SuppressWarnings作用與用法

    用於壓制強制警告信息,以之前介紹的泛型操作爲例,在泛型中如果沒有指定泛型類型則在編譯時期會出現安全警告,而如果加上@SuppressWarnings則可以將安全警告強制壓制。

自定義Annotation

    當我們系統Annotation不能滿足我們的需求時,我們就可以自定義Annotation。

格式

[public ] @interface Annotation 名稱{ 

        數據類型 變量名稱(); 

   }

        按照上述格式自定義一個簡單的Annotation。

public @interface MyDefaultAnnotationNoneParam{     

  }

        之後就可以直接在程序中使用@ MyDefaultAnnotationNoneParam了。

        此外還可以向Annotation中設置參數,使用變量接受參數

public @interface MyDefaultAnnotationSingleParam{ 

    public String value() ;    // 接收設置的內容 

}

         在使用的時候就必須指定變量的值

@ MyDefaultAnnotationSingleParam("月芽之上") 

class Demo{ 

}

         或者也可以使用明確的標記,表示內容賦值給那個參數

public @interface MyDefaultAnnotationMoreParam{ 

    public String key(); 

public String value() ;    // 接收設置的內容 

}

         此時Annotation在使用的時候需要設置兩個參數。一個是key、一個事value.

@ MyDefaultAnnotationMoreParam (key="月芽之上",value="李佔祥") 

class Demo{ 

}

         也可以設置一個數據進去

public @interface MyDefaultAnnotationArrayParam{ 

    public String[] value() ;    // 接收設置的內容 

}

        接收的內容本身是一個數組類型,需要傳遞數據,這一點類似於SuppressWarnings

@ MyDefaultAnnotationArrayParam ({ "月芽之上","李佔祥"}) 

class Demo{ 

}

         以上所定義的全部的Annotation中有一個特點,就是所有的參數內容需要在使用註釋的時候設置上去,那麼也可以爲一個參數設置默認的內容,在聲明的時候使用default即可。

public @interface MyDefaultAnnotationParam{ 

    public String key() default "月芽之上"; 

public String value()default "李佔祥" ;    // 接收設置的內容 

}

         如果設置了默認值,那麼在使用Annotation時就可以不設置內容了(使用默認值)。

        在以上操作中,對於一個Annotation而言 有時候會取固定的取值範圍,只能取固定的幾個值,那麼這時候就需要依靠枚舉來實現。

public enum MyName{    // 定義枚舉類型 

    月芽之上,李佔祥; 

}

        以後的Annotation的取值,只能從這兩個值中間去取。

public @interface MyDefaultAnnotationEnum{ 

    public String name() default MyName."月芽之上"; 

}

         此時以上的Annotation已經設置好了一個枚舉中的內容作爲默認值,那外部在使用此Annotation的時候也需要從枚舉的固定值中取。

Retention和RetentionPolicy

    在定義Annotation時可以使用Retention定義一個Annotation的保存範圍,此Annotation的定義如下:

@Documented

@Retention(vale=RUNTIME)

@Target(vale=ANNOTATION_TYPE)

public @interface Retention{

    RetentionPolicy value();

}

        在以上的Retention定義中定義了一個RetentionPolicy的變量,此變量用於指定Annotation的保存範圍。範圍分爲三種:

在三個範圍中,最需要關心的即使RUNTIME範圍,因此此時在執行的時候氣作用。

通過反射取得Annotation內容

    一個Annotation如果要想變得有意義,就必須結合反射機制取得Annotation中設置的全部內容。

取得Annotation內容的常見方法

package reflectannotation ; 

public class SimpleBeanOne{ 

    @SuppressWarnings("unchecked") 

    @Deprecated 

    @Override 

    public String toString(){ 

        return "Hello LiXingHua!!!" ; 

    } 

}

        同時設置了三個Annotation,那麼此時注意,只有Deprecated的Annotation定義的範圍是RUNTIME範圍,所以此時通過反射只能取得一個。

import java.lang.annotation.Annotation ; 

import java.lang.reflect.Method ; 

public class ReflectDemo01{ 

    public static void main(String args[]) throws Exception{    // 所有異常拋出 

        Class <?> c = null ; 

        c = Class.forName("reflectannotation.SimpleBeanOne") ; 

        Method toM = c.getMethod("toString") ;    // 找到toString()方法 

        Annotation an[] = toM.getAnnotations() ;    // 取得全部的Annotation 

        for(Annotation a:an){    // 使用 foreach輸出 

            System.out.println(a) ; 

        } 

    } 

}

        以上的操作代碼實際是通過三個系統內建的Annotation完成的,那麼特可以自定義一個Annotation

package reflectannotation ; 

import java.lang.annotation.Retention ; 

import java.lang.annotation.RetentionPolicy ; 

@Retention(value=RetentionPolicy.RUNTIME)    // 此Annotation在類執行時依然有效 

public @interface MyDefaultAnnotationReflect{ 

    public String key() default "月芽之上" ; 

    public String value() default "李佔祥" ; 

}

         以上的Annotation範圍是在運行時依然有效,下面定義一個類使用該Annotation。

package reflectannotation ; 

public class SimpleBeanTwo{ 

    @SuppressWarnings("unchecked") 

    @Deprecated 

    @Override 

    @MyDefaultAnnotationReflect(key="月芽之上",value="李佔祥") 

    public String toString(){ 

        return "Hello lzx!!!" ; 

    } 

}

        下面通過反射取得指定的Annotation,因爲現在唯一設置的內容就是MyDefaultAnnotationReflect

import reflectannotation.MyDefaultAnnotationReflect ; 

import java.lang.annotation.Annotation ; 

import java.lang.reflect.Method ; 

public class ReflectDemo02{ 

    public static void main(String args[]) throws Exception{    // 所有異常拋出 

        Class <?> c = null ; 

        c = Class.forName("reflectannotation.SimpleBeanTwo") ; 

        Method toM = c.getMethod("toString") ;    // 找到toString()方法 

        if(toM.isAnnotationPresent(MyDefaultAnnotationReflect.class)){ 

            // 判斷是否是指定的Annotation 

            MyDefaultAnnotationReflect mda = null ; 

            mda = toM.getAnnotation(MyDefaultAnnotationReflect.class) ;    // 得到指定的Annotation 

            String key = mda.key() ;    // 取出設置的key 

            String value = mda.value() ;    // 取出設置的value 

            System.out.println("key = " + key) ; 

            System.out.println("value = " + value) ; 

        } 

    } 

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