Java中的Annotation詳解

1、三個基本Annotation

Annotation簡介

從JDK5.0開始,Java增長了對元數據(MetaData)的支持,也就是Annotation(註解,也有地方稱之爲註釋),其實說白了就是代碼裏的特殊標記,這些標記能夠在編譯、類加載、運行時被讀取,並執行相應的處理。經過使用Annotation,程序開發人員能夠在不改變原有邏輯的狀況下,在源文件嵌入一些補充的信息。代碼分析工具、開發工具和部署工具能夠經過這些補充信息進行驗證或者進行部署。java

Annotation提供了一條爲程序元素設置元數據的方法,從某些方面來看,Annotation就像修飾符同樣被使用,可用於修飾包、類、構造器、方法、成員變量、參數、局部變量的聲明,這些信息被存儲在Annotation的「name=value」對中。Annotation是一個接口,程序能夠經過反射來獲取指定程序元素的Annotation對象而後經過Annotation對象取得註釋裏的元數據。編程

Annotation能被用來爲程序元素(類、方法、成員變量等)設置元數據。值得指出的是:Annotation不能影響程序代碼執行,不管增長、刪除Annotation,代碼都始終如一地執行。若是但願讓程序中的Annotation能在運行時起必定做用,只有經過某種配套的工具對Annotation中的信息進行訪問和處理,訪問和處理Annotation的工具統稱APT(AnnotationProcessing Tool)。eclipse

Java中提供三個基本的Annotation

限定重寫父類方法:@Override

@Override就是用來指定方法重寫的,它能夠強調一個子類必需要覆蓋父類的方法。以下程序中使用@Override指定子類Apple的info方法必須重寫父類方法ide

  1. public class Fruit  
  2. {  
  3.     public void info()  
  4.     {   
  5.         System.out.println("水果的info方法。。。");   
  6.     }  
  7. }   
  8.   
  9. class Apple extends Fruit  
  10. {  
  11.     //使用@Override指定下面方法必須重寫父類方法  
  12.     @Override   
  13. //  public void info()  
  14.     public void inf0()  
  15.     {   
  16.         System.out.println("蘋果重寫水果的info方法。。。");   
  17.     }  
  18. }  

若是重寫的方法名以及參數與父類一直那麼看不出@Override什麼做用,可是若是重寫的方法與父類的方法不一致,那麼程序將在編譯階段出錯。也就是說這個註解的做用就是幫助咱們避免一些低級錯誤。工具

標示已過期:@Deprecated

@Deprecated用於表示某個程序元素(類、方法等)已過期,當其餘程序使用已過期的類、方法時,編譯器將會給出警告。以下程序指定Apple類中的info方法已過期,其餘程序中使用Apple類的info方法時編譯器將會給出警告。開發工具

  1. class Apple  
  2. {  
  3.     //定義info方法已過期  
  4.     @Deprecated  
  5.     public void info()  
  6.     {  
  7.         System.out.println("Apple的info方法");  
  8.     }  
  9. }  
  10. public class DeprecatedTest  
  11. {  
  12.     public static void main(String[] args)   
  13.     {  
  14.         //下面使用info方法時將會被編譯器警告  
  15.         new Apple().info();  
  16.     }     
  17. }  

在eclipse中標註此註解的方法會被刪除線標記出來,以引發編程人員的注意。測試

抑制編譯器警告:@SuppressWarnings

@SuppressWarnings指示被Annotation標識的程序元素(以及在該程序元素中的全部子元素)取消顯示指定的編譯器警告。@SuppressWarnings會一直做用於該程序元素的全部子元素,例如使用@SuppressWarnings標識的一個類來取消顯示某個編譯器警告,同時又標識該類裏某個方法取消顯示另外一個編譯器警告,那麼在此方法中同時取消顯示這兩個編譯器警告。ui

一般狀況下若是程序中使用沒有泛型限制的集合將會引發編譯器警告,爲了不這種編譯器警告,可使用@SuppressWarnings這個註解,下面程序取消了沒有使用泛型的編譯器警告。.net

  1. @SuppressWarnings(value="unchecked")  
  2. public class SuppressWarningsTest  
  3. {  
  4.     public static void main(String[] args)   
  5.     {  
  6.         List<String> myList = new ArrayList();          
  7.     }     
  8. }  

正如程序中所看到的,當咱們使用此註解來關閉編譯器警告時,必定須要在括號裏使用name=value對來爲該註解成員變量設置值。對象

以上就是對註解的一個簡單的介紹


2、Annotation的工做原理

本文將介紹Annotation的原理,以及如何自定義Annotation,並利用Annotation來完成一些實際的功能。

定義Annotation

定義新的Annotation類型使用@interface關鍵字,這從必定意義上說明Annotation和接口的定義是有類似之處的。以下代碼定義了一個Annotation

  1.     //使用DK的元數據Annotation:Retention  
  2.     @Retention(RetentionPolicy.RUNTIME)  
  3.     //使用JDK的元數據Annotation:Target  
  4.     @Target(ElementType.METHOD)  
  5.     //定義一個標記註釋,不包含任何成員變量,即不可傳入元數據  
  6. public @interface Testable{  
  7.       
  8. }  

使用Annotation

定義了Annotation以後就能夠在程序的任何地方使用該Annotation,對於Annotation的使用和public、final這樣的修飾符很像,一般能夠修飾類、方法、變量、接口等定義(默認狀況下,Annotation用於修飾任何程序元素)。以下代碼,就是使用了上面的Annotation修飾方法。

  1. public class MyTest {  
  2.     //使用@Testable標記註釋指定該方法是可測試的  
  3.     @Testable  
  4.     public static void m1(){  
  5.           
  6.     }  
  7.     public static void m2(){  
  8.           
  9.     }  
  10.     //使用@Testable標記註釋指定該方法是可測試的  
  11.     @Testable  
  12.     public static void m3(){  
  13.         throw new RuntimeException("Boom");  
  14.     }  
  15.     public static void m4(){  
  16.           
  17.     }  
  18.     //使用@Testable標記註釋指定該方法是可測試的  
  19.     @Testable  
  20.     public static void m5(){  
  21.           
  22.     }  
  23.     public static void m6(){  
  24.           
  25.     }  
  26.     //使用@Testable標記註釋指定該方法是可測試的  
  27.     @Testable  
  28.     public static void m7(){  
  29.         throw new RuntimeException("Crash");  
  30.     }  
  31.     public static void m8(){  
  32.           
  33.     }  
  34. }  

提取Annotation

一個類或者一個方法使用Annotation修飾以後須要經過反射來提取Annotation的信息。須要注意當一個Annotation類型被定義爲運行時Annotation後該註釋纔是運行時可見的,當class文件被裝載時被保存在class文件中的Annotation纔會被虛擬機讀取。下面代碼就是將Annotation信息提取出來,根據這些信息進行相應的操做。在這裏是若是某個方法被標記爲能夠測試的則調用這個方法。

  1. public class TestProcessor {  
  2.     public static void process(String clazz)throws ClassNotFoundException{  
  3.         int passed=0;  
  4.         int failed=0;  
  5.         //遍歷obj對象的全部方法  
  6.         for(Method m :Class.forName(clazz).getMethods()){  
  7.             //若是包含@Testable標記註釋  
  8.             if(m.isAnnotationPresent(Testable.class)){  
  9.                 try{  
  10.                     //調用m方法  
  11.                     m.invoke(null);  
  12.                     //passed加1  
  13.                     passed++;  
  14.                 }catch (Exception ex) {  
  15.                     System.out.printf("方法"+m+"運行失敗,異常"+ex.getCause()+"\n");  
  16.                     failed++;  
  17.                 }  
  18.             }  
  19.         }  
  20.         //統計測試結果  
  21.         System.out.println("共運行了:"+(passed+failed)+"個方法,其中:\n失敗了:"+failed+",個,\n成功了:"+passed+"個!\n");  
  22.     }  
  23. }  

其中程序的主程序以下

  1. public class RunTests {  
  2.     public static void main(String[] args) throws Exception{  
  3.         //處理Mytest類  
  4.         TestProcessor.process("annotation.MyTest");  
  5.     }  
  6. }  

運行結果以下

工做原理

上面僅僅是一個簡單地Annotation的使用,更復雜一些的Annotation與上面的這個例子原理是同樣的,只不過相應的邏輯判斷以及涉及到的Annotation中的內容較爲複雜而已。可是核心的部分就是藉助一個操做類經過反射的方式提取Annotation信息,進行操做,簡而言之:無反射,不註釋(Annotation)


原文連接:http://blog.csdn.net/beijiguangyong/article/details/8685452

相關文章
相關標籤/搜索