I want to fly higher
          programming Explorer
          posts - 114,comments - 263,trackbacks - 0
              Java 反射是Java語言的一個很重要的特征。它允許運行中的 Java 程序對自身進行檢查,并能直接操作程序的內部屬性。例如,使用它能獲得Java 類中各成員的名稱并顯示出來。

                 Java 反射機制主要提供了以下功能:

          a.在運行時判斷任意一個對象所屬的類。

          b.在運行時構造任意一個類的對象。

          c.在運行時判斷任意一個類所具有的成員變量和方法。

          d.在運行時調用任意一個對象的方法。

          JDK中,主要由以下類來實現Java反射機制,這些類在java.lang.reflect包中:

          Class類:代表一個類。

          Field 類:代表類的成員變量(成員變量也稱為類的屬性)。

          Method類:代表類的方法。

          Constructor 類:代表類的構造方法。

          Array類:提供了動態創建數組,以及訪問數組的元素的靜態方法。

             下面寫了一個程序:設計了一個POJO類。所謂POJO類,本人粗淺的理解即和JavaBean類似,只有字段和setter/getter方法。然后在主函數通過反射,在控制臺打印該POJO類的所有字段和方法。
              
          本人設計的POJO類為WorkerPOJO.java,然后另一個測試類為POJOReflection.java,在main函數中負責打印該類的所有字段和方法。程序見下:

          WorkerPOJO.java

           1package com.xpec.landon.trainjava.annotation;
           2/**
           3 * POJO類,和JavaBean相似
           4 * @author landon
           5 *
           6 */

           7public class WorkerPOJO{
           8 private String name;
           9 private int age;
          10 
          11 /**
          12  * 用Annotation修飾
          13  * @return 姓名
          14  */

          15 @WorkerPOJOAnnotation(name = "landon",age = 22)
          16 public String getName() {
          17  return name;
          18 }

          19 public void setName(String name) {
          20  this.name = name;
          21 }

          22 public int getAge() {
          23  return age;
          24 }

          25 public void setAge(int age) {
          26  this.age = age;
          27 }

          28
          29}

          30
          31


          POJOReflection.java
              

           1package com.xpec.landon.trainjava.annotation;
           2import java.lang.reflect.Field;
           3import java.lang.reflect.Modifier;
           4import java.lang.reflect.Method;
           5
           6
           7/**
           8 * 運用Java的反射機制,輸出POJO類的字段和方法(新增了Annotation的修飾)
           9 * @author landon
          10 *
          11 */

          12public class POJOReflectionTest {
          13 public static void main(String[] args)
          14 {
          15  try 
          16  {
          17   //加載WorkPOJO,注意這里一定要寫全類名,包括包名,因為包名是類名的一部分
          18   Class pojo = Class.forName("com.xpec.landon.trainjava.annotation.WorkerPOJO");
          19   //獲取域的數組
          20   Field []fieldList = pojo.getDeclaredFields();
          21   //獲取方法的數組
          22   Method []methodList = pojo.getDeclaredMethods();
          23   
          24   System.out.println("WorkerPOJO類的所有字段:");
          25   System.out.println("修飾符" + "    " + "類型" + "                   " + "字段名");
          26   
          27   for(int i = 0;i < fieldList.length;i++)
          28   {
          29    Field field = fieldList[i];
          30    //用下面的形式獲取具體的修飾符
          31    System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getType() + " " + field.getName());
          32   }

          33   
          34   System.out.println();
          35   System.out.println("WorkerPOJO類的所有方法(不包括annotation修飾的方法):");
          36   
          37   for(int j = 0;j < methodList.length;j++)
          38   {
          39    Method method = methodList[j];
          40    //判斷方法是否被Annotation修飾
          41    boolean methodAnnotation = method.isAnnotationPresent(WorkerPOJOAnnotation.class);
          42    
          43    //如果被annotation修飾,則過濾掉該方法,即不輸出
          44    if(methodAnnotation)
          45    {
          46     continue;
          47    }

          48    //獲取方法參數列表
          49    Class parameters[] = method.getParameterTypes();
          50    
          51    System.out.print(Modifier.toString(method.getModifiers()) + " " + method.getReturnType() + " " + method.getName() + " (");
          52    
          53    for(int k = 0;k < parameters.length;k++)
          54    {
          55     System.out.print(parameters[k].toString());
          56    }

          57    
          58    System.out.println(")");
          59   }

          60  }

          61  catch(ClassNotFoundException exception1)
          62  {
          63   exception1.printStackTrace();
          64  }

          65  
          66 }

          67
          68}

          69
          70

           

              下面是程序的一個運行截圖:



              可以看到,在WorkerPOJO類中引入了Annotation。下面,我們詳細介紹一下Annotation:
              在使用JUnit4中,我們可以看到在每個測試方法前面都有一個@Test標記,這就是傳說中的Annotation
              
          Annotation 提供了一條與程序元素關聯任何信息或者任何元數據(metadata)的途徑。從某些方面看,annotation就像修飾符一樣被使用,并應用于包、類型、構造方法、方法、成員變量、參數、本地變量的聲明中。這些信息被存儲在annotation“name=value”結構對中。 annotation類型是一種接口,能夠通過java反射API的方式提供對其信息的訪問。
              
          annotation能被用來為某個程序元素(類、方法、成員變量等)關聯任何的信息。需要注意的是,這里存在著一個基本的潛規則:annotaion不能影響程序代碼的執行,無論增加、刪除 annotation,代碼都始終如一的執行。另外,盡管一些annotation通過java的反射api方法在運行時被訪問,而java語言解釋器在工作時忽略了這些annotation。正是由于java虛擬機忽略了annotation,導致了annotation類型在代碼中是不起作用的;只有通過某種配套的工具才會對annotation類型中的信息進行訪問和處理。
              
           annotation是與一個程序元素相關聯信息或者元數據的標注。它從不影響
          ava程序的執行,但是對例如編譯器警告或者像文檔生成器等輔助工具產生影響。
              
          我的理解是:Annotation是繼承自java.lang.annotation.Annotation的類,用于向程序分析工具或虛擬機提供package class field methed 等方面的信息,它和其他類沒什么區別,除了使用方式。
              下面寫了一個簡單的Annotation:WorkerPOJOAnnotation.java

           1package com.xpec.landon.trainjava.annotation;
           2import java.lang.annotation.Documented;
           3import java.lang.annotation.ElementType;
           4import java.lang.annotation.Retention;
           5import java.lang.annotation.RetentionPolicy;
           6import java.lang.annotation.Target;
           7
           8/**
           9 * 修飾WorkerPOJO類方法的一個Annotation
          10 * @author landon
          11 *
          12 */

          13
          14@Target(ElementType.METHOD)
          15@Retention(RetentionPolicy.RUNTIME)
          16@Documented
          17public @interface WorkerPOJOAnnotation {
          18 String name();
          19 int age();
          20
          21}

          22
          23


              其中@Target里面的ElementType是用來指定Annotation類型可以用在哪一些元素上的,包括TYPE(類型),METHOD(方法),FIELD(字段),PARAMETER(參數)等。其中TYPE是指可以用在Class,Interface等類型上。下面給出用jad反編譯出的ElementType中的靜態變量的截圖:

              另外@Retention中的RetentionPolicy是指Annotation中的信息保留方式,分別是SOURCE,CLASS RUNTIME. SOURCE代表的是這個Annotation類型的信息只會保留在程序源碼里,源碼如果經過了編譯之后,Annotation的數據就會消失,并不會保留在編譯好的.class文件里面。 ClASS的意思是這個Annotation類型的信息保留在程序源碼里,同時也會保留在編譯好的.class文件里面,在執行的時候,并不會把這一些信息加載到虛擬機(JVM)中去.注意一下,當你沒有設定一個Annotation類型的Retention值時,系統默認值是CLASS. 第三個,RUNTIME,表示在源碼、編譯好的.class文件中保留信息,在執行的時候會把這一些信息加載到JVM中去的.
              下面給出用jad反編譯出的RetentionPolicy中的靜態變量的截圖
              
              最后的一個Annotation@Documented是指目的就是讓這一個Annotation類型的信息能夠顯示在Java API說明文檔上。

              下面將上面自己設計的WorkerPOJOAnnotation應用在了WorkerPOJO類的一個方法前面:
              然后在控制臺輸出了沒有被Annotation注釋的字段和方法,運行后可以看到不包括getName方法。
              最后我們可以用Junit4書寫一個測試用例: POJOReflectionJunit4Test.java
              

           1package com.xpec.landon.trainjava.annotation;
           2import java.lang.reflect.Field;
           3import java.lang.reflect.Method;
           4
           5import javax.activation.FileDataSource;
           6
           7import junit.framework.Assert;
           8
           9import org.junit.After;
          10import org.junit.Before;
          11import org.junit.Test;
          12
          13/**
          14 * 關于Java反射以及Annotation的一個TestCase
          15 * @author landon
          16 *
          17 */

          18
          19public class POJOReflectionJunit4Test {
          20 private Class pojo;
          21 private Field []fieldList;
          22 private Method[] methodList;
          23
          24 @Before
          25 public void setUp() throws Exception {
          26  //加載類WorkPOJO
          27  pojo = Class.forName("com.xpec.landon.trainjava.annotation.WorkerPOJO");
          28  //獲取域的數組
          29  fieldList = pojo.getDeclaredFields();
          30  //獲取方法的數組
          31  methodList = pojo.getDeclaredMethods();
          32 }

          33 
          34 //測試字段和方法的個數
          35 @Test
          36 public void testSize()
          37 {
          38  Assert.assertEquals(2, fieldList.length);
          39  Assert.assertEquals(4, methodList.length);
          40 }

          41
          42 //測試字段是否帶有annotations
          43 @Test
          44 public void isFieldAnnotation()
          45 {
          46  for(int i = 0;i < fieldList.length;i++)
          47  {
          48   Assert.assertEquals(false, fieldList[i].isAnnotationPresent(WorkerPOJOAnnotation.class));
          49  }

          50 }

          51 
          52 //測試方法是否帶有annotations
          53 @Test
          54 public void isMethodAnnotation()
          55 {
          56  for(int i = 0;i < methodList.length;i++)
          57  {
          58   Assert.assertEquals(false, methodList[i].isAnnotationPresent(WorkerPOJOAnnotation.class));
          59  }

          60 }

          61 
          62 @After
          63 public void tearDown() throws Exception {
          64 }

          65
          66}

          67

          posted on 2010-07-14 12:19 landon 閱讀(2681) 評論(0)  編輯  收藏 所屬分類: Program
          主站蜘蛛池模板: 义马市| 梁平县| 金湖县| 紫金县| 永定县| 集贤县| 大英县| 体育| 新干县| 眉山市| 贵阳市| 教育| 永修县| 赣州市| 扎鲁特旗| 建德市| 西城区| 元谋县| 神木县| 蒙山县| 根河市| 乌兰察布市| 汉寿县| 青浦区| 博白县| 克什克腾旗| 萨嘎县| 巴林右旗| 平昌县| 苍梧县| 荃湾区| 庆城县| 德阳市| 长春市| 永州市| 布尔津县| 扶沟县| 西华县| 广汉市| 海口市| 高清|