上篇文章介紹了反射的一些基礎知識以及應用案例,本文將介紹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) ; } } }