dyerac  
          dyerac In Java
          公告

          日歷
          <2007年7月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234
          統(tǒng)計(jì)
          • 隨筆 - 36
          • 文章 - 10
          • 評(píng)論 - 94
          • 引用 - 0

          導(dǎo)航

          常用鏈接

          留言簿(5)

          隨筆分類(49)

          隨筆檔案(36)

          文章分類(11)

          文章檔案(10)

          相冊(cè)

          dyerac

          搜索

          •  

          積分與排名

          • 積分 - 79790
          • 排名 - 705

          最新隨筆

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

           

          基礎(chǔ)學(xué)習(xí)教程:Java Annotation入門

          摘要:

           本文針對(duì)java初學(xué)者或者annotation初次使用者全面地說明了annotation的使 用方法、定義方式、分類。初學(xué)者可以通過以上的說明制作簡單的annotation程序,但是對(duì)于一些高級(jí)的annotation應(yīng)用(例如使用自定義 annotation生成javabean映射xml文件)還需要進(jìn)一步的研究和探討。涉及到深入annotation的內(nèi)容,作者將在后文《Java Annotation高級(jí)應(yīng)用》中談到。

           同時(shí),annotation運(yùn)行存在兩種方式:運(yùn)行時(shí)、編譯時(shí)。上文中討論的都是在運(yùn)行時(shí)的annotation應(yīng)用,但在編譯時(shí)的annotation應(yīng)用還沒有涉及,

           一、為什么使用Annotation:

           在JAVA應(yīng)用中,我們常遇到一些需要使用模版代碼。例如,為了編寫一個(gè)JAX-RPC web service,我們必須提供一對(duì)接口和實(shí)現(xiàn)作為模版代碼。如果使用annotation對(duì)遠(yuǎn)程訪問的方法代碼進(jìn)行修飾的話,這個(gè)模版就能夠使用工具自動(dòng)生成。

           另外,一些API需要使用與程序代碼同時(shí)維護(hù)的附屬文件。例如,JavaBeans需要一個(gè) BeanInfo Class與一個(gè)Bean同時(shí)使用/維護(hù),而EJB則同樣需要一個(gè)部署描述符。此時(shí)在程序中使用annotation來維護(hù)這些附屬文件的信息將十分便利 而且減少了錯(cuò)誤。

           二、Annotation工作方式:

           在5.0版之前的Java平臺(tái)已經(jīng)具有了一些ad hoc annotation機(jī)制。比如,使用transient修飾符來標(biāo)識(shí)一個(gè)成員變量在序列化子系統(tǒng)中應(yīng)被忽略。而@deprecated這個(gè) javadoc tag也是一個(gè)ad hoc annotation用來說明一個(gè)方法已過時(shí)。從Java5.0版發(fā)布以來,5.0平臺(tái)提供了一個(gè)正式的annotation功能:允許開發(fā)者定義、使用 自己的annoatation類型。此功能由一個(gè)定義annotation類型的語法和一個(gè)描述annotation聲明的語法,讀取annotaion 的API,一個(gè)使用annotation修飾的class文件,一個(gè)annotation處理工具(apt)組成。

           annotation并不直接影響代碼語義,但是它能夠工作的方式被看作類似程序的工具或者類庫,它會(huì)反過來對(duì)正在運(yùn)行的程序語義有所影響。annotation可以從源文件、class文件或者以在運(yùn)行時(shí)反射的多種方式被讀取。

           當(dāng)然annotation在某種程度上使javadoc tag更加完整。一般情況下,如果這個(gè)標(biāo)記對(duì)java文檔產(chǎn)生影響或者用于生成java文檔的話,它應(yīng)該作為一個(gè)javadoc tag;否則將作為一個(gè)annotation.

           三、Annotation使用方法:

           1.類型聲明方式:

           通常,應(yīng)用程序并不是必須定義annotation類型,但是定義annotation類型并非難事。Annotation類型聲明于一般的接口聲明極為類似,區(qū)別只在于它在interface關(guān)鍵字前面使用"@"符號(hào)。

           annotation類型的每個(gè)方法聲明定義了一個(gè)annotation類型成員,但方法聲明不必 有參數(shù)或者異常聲明;方法返回值的類型被限制在以下的范圍:primitives、String、Class、enums、annotation和前面類 型的數(shù)組;方法可以有默認(rèn)值。

           下面是一個(gè)簡單的annotation類型聲明:

           清單1:

           

              /**
               * Describes the Request-For-Enhancement(RFE) that led
               * to the presence of the annotated API element.
               */
              public @interface RequestForEnhancement {
                  int    id();
                  String synopsis();
                  String engineer() default "[unassigned]";
                  String date();    default "[unimplemented]";
              }

           代碼中只定義了一個(gè)annotation類型RequestForEnhancement.

           2.修飾方法的annotation聲明方式:

           annotation 是一種修飾符,能夠如其它修飾符(如public、static、final)一般使用。習(xí)慣用法是annotaions用在其它的修飾符前面。 annotations由"@+annotation類型+帶有括號(hào)的成員-值列表"組成。這些成員的值必須是編譯時(shí)常量(即在運(yùn)行時(shí)不變)。

           A:下面是一個(gè)使用了RequestForEnhancement annotation的方法聲明:

           清單2:

              @RequestForEnhancement(
                  id       = 2868724,
                  synopsis = "Enable time-travel",
                  engineer = "Mr. Peabody",
                  date     = "4/1/3007"
              )
              public static void travelThroughTime(Date destination) { ... }

           B:當(dāng)聲明一個(gè)沒有成員的annotation類型聲明時(shí),可使用以下方式:


             清單3:

              /**
               * Indicates that the specification of the annotated API element
               * is preliminary and subject to change.
               */
              public @interface Preliminary { }

           
           作為上面沒有成員的annotation類型聲明的簡寫方式:

           

           清單4:



           

              @Preliminary public class TimeTravel { ... }


           C:如果在annotations中只有唯一一個(gè)成員,則該成員應(yīng)命名為value:

           

           清單5:



           

              /**
               * Associates a copyright notice with the annotated API element.
               */
              public @interface Copyright {
                  String value();
              }


           更為方便的是對(duì)于具有唯一成員且成員名為value的annotation(如上文),在其使用時(shí)可以忽略掉成員名和賦值號(hào)(=):

           

           清單6:


           

              @Copyright("2002 Yoyodyne Propulsion Systems")
              public class OscillationOverthruster { ... }


           3.一個(gè)使用實(shí)例:

           

           結(jié)合上面所講的,我們?cè)谶@里建立一個(gè)簡單的基于annotation測試框架。首先我們需要一個(gè)annotation類型來表示某個(gè)方法是一個(gè)應(yīng)該被測試工具運(yùn)行的測試方法。

           

           清單7:


           

              import java.lang.annotation.*;

              /**
               * Indicates that the annotated method is a test method.
               * This annotation should be used only on parameterless static methods.
               */
              @Retention(RetentionPolicy.RUNTIME)
              @Target(ElementType.METHOD)
              public @interface Test { }


           值得注意的是annotaion類型聲明是可以標(biāo)注自己的,這樣的annotation被稱為“meta-annotations”。

           

          在上面的代碼中,@Retention(RetentionPolicy.RUNTIME)這個(gè)meta-annotation表示了此類型的 annotation將被虛擬機(jī)保留使其能夠在運(yùn)行時(shí)通過反射被讀取。而@Target(ElementType.METHOD)表示此類型的 annotation只能用于修飾方法聲明。

           

           下面是一個(gè)簡單的程序,其中部分方法被上面的annotation所標(biāo)注:

           

           清單8:


           

              public class Foo {
                  @Test public static void m1() { }
                  public static void m2() { }
                  @Test public static void m3() {
                      throw new RuntimeException("Boom");
                  }
                  public static void m4() { }
                  @Test public static void m5() { }
                  public static void m6() { }
                  @Test public static void m7() {
                      throw new RuntimeException("Crash");
                  }
                  public static void m8() { }
              }

          Here is the testing tool:

              import java.lang.reflect.*;

              public class RunTests {
                 public static void main(String[] args) throws Exception {
                    int passed = 0, failed = 0;
                    for (Method m : Class.forName(args[0]).getMethods()) {
                       if (m.isAnnotationPresent(Test.class)) {
                          try {
                             m.invoke(null);
                             passed++;
                          } catch (Throwable ex) {
                             System.out.printf("Test %s failed: %s %n", m, ex.getCause());
                             failed++;
                          }
                       }
                    }
                    System.out.printf("Passed: %d, Failed %d%n", passed, failed);
                 }
              }


          這個(gè)程序從命令行參數(shù)中取出類名,并且遍歷此類的所有方法,嘗試調(diào)用其中被上面的測試annotation類型標(biāo)注過的方法。在此過程中為了找出哪些方法 被annotation類型標(biāo)注過,需要使用反射的方式執(zhí)行此查詢。如果在調(diào)用方法時(shí)拋出異常,此方法被認(rèn)為已經(jīng)失敗,并打印一個(gè)失敗報(bào)告。最后,打印運(yùn) 行通過/失敗的方法數(shù)量。

           

           下面文字表示了如何運(yùn)行這個(gè)基于annotation的測試工具:

           

           清單9:



           

              $ java RunTests Foo
              Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom
              Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash
              Passed: 2, Failed 2


           四、Annotation分類:

           

           根據(jù)annotation的使用方法和用途主要分為以下幾類:

           

           1.內(nèi)建Annotation――Java5.0版在java語法中經(jīng)常用到的內(nèi)建Annotation:

           

           @Deprecated用于修飾已經(jīng)過時(shí)的方法;

           

           @Override用于修飾此方法覆蓋了父類的方法(而非重載);

           

           @SuppressWarnings用于通知java編譯器禁止特定的編譯警告。

           

           下面代碼展示了內(nèi)建Annotation類型的用法:

           

           清單10:



           

          package com.bjinfotech.practice.annotation;

          /**
           *
          演示如何使用java5內(nèi)建的annotation
           *
          參考資料:

           * http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html
           * http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
           * http://mindprod.com/jgloss/annotations.html
           * @author cleverpig
           *
           */
          import java.util.List;

          public class UsingBuiltInAnnotation {
                  //
          食物類
                  class Food{}
                  //
          干草類
                  class Hay extends Food{}
                  //
          動(dòng)物類
                  class Animal{
                          Food getFood(){
                                  return null;
                          }
                          //
          使用Annotation聲明Deprecated方法
                          @Deprecated
                          void deprecatedMethod(){
                          }
                  }
                  //
          馬類-繼承動(dòng)物類
                  class Horse extends Animal{
                          //
          使用Annotation聲明覆蓋方法
                          @Override
                          Hay getFood(){
                                  return new Hay();
                          }
                          //
          使用Annotation聲明禁止警告
                          @SuppressWarnings({"deprecation","unchecked"})
                          void callDeprecatedMethod(List horseGroup){
                                  Animal an=new Animal();
                                  an.deprecatedMethod();
                                  horseGroup.add(an);
                          }
                  }
          }


           2.開發(fā)者自定義Annotation:由開發(fā)者自定義Annotation類型。

           

           下面是一個(gè)使用annotation進(jìn)行方法測試的sample:

           

           AnnotationDefineForTestFunction類型定義如下:

           

           清單11:

           

          package com.bjinfotech.practice.annotation;

          import java.lang.annotation.*;
          /**
           *
          定義annotation
           * @author cleverpig
           *
           */
          //
          加載在VM中,在運(yùn)行時(shí)進(jìn)行映射

          @Retention(RetentionPolicy.RUNTIME)
          //
          限定此annotation只能標(biāo)示方法
          @Target(ElementType.METHOD)
          public @interface AnnotationDefineForTestFunction{}


           測試annotation的代碼如下:

           

           清單12:



          Java Annotation 高級(jí)應(yīng)用

          作者:cleverpig





          版權(quán)聲明:本文可以自由轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
          作者:cleverpig(作者的Blog:http://blog.matrix.org.cn/page/cleverpig)
          原文:http://www.matrix.org.cn/resource/article/44/44062_Java+Annotation+Apt.html
          關(guān)鍵字:java,annotation,apt

          前言:
          前不久在matrix上先后發(fā)表了《java annotation 入門》《java annotation 手冊(cè)》兩 篇文章,比較全面的對(duì)java annotation的語法、原理、使用三方面進(jìn)行了闡述。由于《入門》中的簡單例程雖然簡單明了的說明了annotation用法,但給大家的感覺可能 是意猶未見,所以在此行文《java annotation高級(jí)應(yīng)用》,具體實(shí)例化解釋annotation和annotation processing tool(APT)的使用。望能對(duì)各位的有所幫助。

          一、摘要:
          《java annotation高級(jí)應(yīng)用》具體實(shí)例化解釋annotation和annotation processing tool(APT)的使用。望能對(duì)各位的有所幫助。本文列舉了用于演示annotation的BRFW演示框架、演示APT的apt代碼實(shí)例,并對(duì)其進(jìn)行 較為深度的分析,希望大家多多提意見。

          二、annotation實(shí)例分析
          1.BRFW(Beaninfo Runtime FrameWork)定義:
          本人編寫的一個(gè)annotation功能演示框架。顧名思義,BRFW就是在運(yùn)行時(shí)取得bean信息的框架。

          2.BRFW的功能:
          A.源代碼級(jí)annotation:在bean的源代碼中使用annotation定義bean的信息;
          B.運(yùn)行時(shí)獲取bean數(shù)據(jù):在運(yùn)行時(shí)分析bean class中的annotation,并將當(dāng)前bean class中field信息取出,功能類似xdoclet;
          C.運(yùn)行時(shí)bean數(shù)據(jù)的xml綁定:將獲得的bean數(shù)據(jù)構(gòu)造為xml文件格式展現(xiàn)。熟悉j2ee的朋友知道,這個(gè)功能類似jaxb。

          3.BRFW框架:
          BRFW主要包含以下幾個(gè)類:
          A.Persistent類:定義了用于修飾類的固有類型成員變量的annotation。
          B.Exportable類:定義了用于修飾Class的類型的annotation。
          C.ExportToXml類:核心類,用于完成BRFW的主要功能:將具有Exportable Annotation的bean對(duì)象轉(zhuǎn)換為xml格式文本。
          D.AddressForTest類:被A和B修飾過的用于測試目的的地址bean類。其中包含了地址定義所必需的信息:國家、省級(jí)、城市、街道、門牌等。
          E.AddressListForTest類: 被A和B修飾過的友人通訊錄bean類。其中包含了通訊錄所必備的信息:友人姓名、年齡、電話、住址(成員為AddressForTest類型的 ArrayList)、備注。需要說明的是電話這個(gè)bean成員變量是由字符串類型組成的ArrayList類型。由于朋友的住址可能不唯一,故這里的住 址為由AddressForTest類型組成的ArrayList。
          從上面的列表中,可以發(fā)現(xiàn)A、B用于修飾bean類和其類成員;C主要用于取出bean類的數(shù)據(jù)并將其作xml綁定,代碼中使用了E作為測試類;E中可能包含著多個(gè)D。
          在了解了這個(gè)簡單框架后,我們來看一下BRFW的代碼吧!

          4.BRFW源代碼分析:
          A.Persistent類:
          清單1:

          package com.bjinfotech.practice.annotation.runtimeframework;

          import java.lang.annotation.*;

          /**
          * 用于修飾類的固有類型成員變量的annotation
          * @author cleverpig
          *
          */
          @Retention(RetentionPolicy.RUNTIME)
          @Target(ElementType.FIELD)
          public @interface Persistent {
                  String value() default "";
          }


          B.Exportable類:
          清單2:

          package com.bjinfotech.practice.annotation.runtimeframework;

          import java.lang.annotation.*;

          /**
          * 用于修飾類的類型的annotation
          * @author cleverpig
          *
          */
          @Retention(RetentionPolicy.RUNTIME)
          @Target(ElementType.TYPE)
          public @interface Exportable {
                  //名稱
                  String name() default "";
                  //描述
                  String description() default "";
                  //省略name和description后,用來保存name值
                  String value() default "";
                  
          }


          C.AddressForTest類:
          清單3:

          package com.bjinfotech.practice.annotation.runtimeframework;

          /**
          * 用于測試的地址類
          * @author cleverpig
          *
          */
          @Exportable("address")
          public class AddressForTest {
                  //國家
                  @Persistent
                  private String country=null;
                  
                  //省級(jí)
                  @Persistent
                  private String province=null;
                  
                  //城市
                  @Persistent
                  private String city=null;
                  
                  //街道
                  @Persistent
                  private String street=null;

                  //門牌
                  @Persistent
                  private String doorplate=null;
                  
                  public AddressForTest(String country,String province,
                                  String city,String street,String doorplate){
                          this.country=country;
                          this.province=province;
                          this.city=city;
                          this.street=street;
                          this.doorplate=doorplate;
                  }
                  
          }


          D.AddressListForTest類:
          清單4:

          package com.bjinfotech.practice.annotation.runtimeframework;

          import java.util.*;

          /**
          * 友人通訊錄
          * 包含:姓名、年齡、電話、住址(多個(gè))、備注
          * @author cleverpig
          *
          */
          @Exportable(name="addresslist",description="address list")
          public class AddressListForTest {
                  //友人姓名
                  @Persistent
                  private String friendName=null;
                  
                  //友人年齡
                  @Persistent
                  private int age=0;
                  
                  //友人電話
                  @Persistent
                  private ArrayList<String> telephone=null;
                  
                  //友人住址:家庭、單位
                  @Persistent
                  private ArrayList<AddressForTest> AddressForText=null;
                  
                  //備注
                  @Persistent
                  private String note=null;
                  
                  public AddressListForTest(String name,int age,
                                  ArrayList<String> telephoneList,
                                  ArrayList<AddressForTest> addressList,
                                  String note){
                          this.friendName=name;
                          this.age=age;
                          this.telephone=new ArrayList<String>(telephoneList);
                          this.AddressForText=new ArrayList<AddressForTest>(addressList);
                          this.note=note;
                          
                  }
          }


          E.ExportToXml類:
          清單5:

          package com.bjinfotech.practice.annotation.runtimeframework;

          import java.lang.reflect.Field;
          import java.util.Collection;
          import java.util.Iterator;
          import java.util.Map;
          import java.util.ArrayList;

          /**
          * 將具有Exportable Annotation的對(duì)象轉(zhuǎn)換為xml格式文本
          * @author cleverpig
          *
          */
          public class ExportToXml {
                  /**
                   * 返回對(duì)象的成員變量的值(字符串類型)
                   * @param field 對(duì)象的成員變量
                   * @param fieldTypeClass 對(duì)象的類型
                   * @param obj 對(duì)象
                   * @return 對(duì)象的成員變量的值(字符串類型)
                   */
                  private String getFieldValue(Field field,Class fieldTypeClass,Object obj){
                          String value=null;
                          
                          try{
                                  if (fieldTypeClass==String.class){
                                          value=(String)field.get(obj);
                                  }
                                  else if (fieldTypeClass==int.class){
                                          value=Integer.toString(field.getInt(obj));
                                  }
                                  else if (fieldTypeClass==long.class){
                                          value=Long.toString(field.getLong(obj));
                                  }
                                  else if (fieldTypeClass==short.class){
                                          value=Short.toString(field.getShort(obj));
                                  }
                                  else if (fieldTypeClass==float.class){
                                          value=Float.toString(field.getFloat(obj));
                                  }
                                  else if (fieldTypeClass==double.class){
                                          value=Double.toString(field.getDouble(obj));
                                  }
                                  else if (fieldTypeClass==byte.class){
                                          value=Byte.toString(field.getByte(obj));
                                  }
                                  else if (fieldTypeClass==char.class){
                                          value=Character.toString(field.getChar(obj));
                                  }
                                  else if (fieldTypeClass==boolean.class){
                                          value=Boolean.toString(field.getBoolean(obj));
                                  }
                          }
                          catch(Exception ex){
                                  ex.printStackTrace();
                                  value=null;
                          }
                          return value;
                  }
                  
                  /**
                   * 輸出對(duì)象的字段,當(dāng)對(duì)象的字段為Collection或者M(jìn)ap類型時(shí),要調(diào)用exportObject方法繼續(xù)處理
                   * @param obj 被處理的對(duì)象
                   * @throws Exception
                   */
                  public void exportFields(Object obj) throws Exception{
                          Exportable exportable=obj.getClass().getAnnotation(Exportable.class);        
                          if (exportable!=null){
                                  if (exportable.value().length()>0){
          //                                System.out.println("Class annotation Name:"+exportable.value());
                                  }
                                  else{
          //                                System.out.println("Class annotation Name:"+exportable.name());
                                  }
                          }
                          else{
          //                        System.out.println(obj.getClass()+"類不是使用Exportable標(biāo)注過的");
                          }
                          
                          //取出對(duì)象的成員變量
                          Field[] fields=obj.getClass().getDeclaredFields();
                          
                          for(Field field:fields){
                                  //獲得成員變量的標(biāo)注
                                  Persistent fieldAnnotation=field.getAnnotation(Persistent.class);
                                  if (fieldAnnotation==null){
                                          continue;
                                  }
                                  //重要:避免java虛擬機(jī)檢查對(duì)私有成員的訪問權(quán)限
                                  field.setAccessible(true);
                                  Class typeClass=field.getType();
                                  String name=field.getName();
                                  String value=getFieldValue(field,typeClass,obj);
                                  
                                  //如果獲得成員變量的值,則輸出
                                  if (value!=null){
                                          System.out.println(getIndent()+"<"+name+">\n"
                                                          +getIndent()+"\t"+value+"\n"+getIndent()+"</"+name+">");
                                  }
                                  //處理成員變量中類型為Collection或Map
                                  else if ((field.get(obj) instanceof Collection)||
                                                  (field.get(obj) instanceof Map)){
                                          exportObject(field.get(obj));
                                  }
                                  else{
                                          exportObject(field.get(obj));
                                  }
                                  
                          }
                  }
                  
                  //縮進(jìn)深度
                  int levelDepth=0;
                  //防止循環(huán)引用的檢查者,循環(huán)引用現(xiàn)象如:a包含b,而b又包含a
                  Collection<Object> cyclicChecker=new ArrayList<Object>();
                  
                  /**
                   * 返回縮進(jìn)字符串
                   * @return
                   */
                  private String getIndent(){
                          String s="";
                          for(int i=0;i<levelDepth;i++){
                                  s+="\t";
                          }
                          return s;
                  }
                  /**
                   * 輸出對(duì)象,如果對(duì)象類型為Collection和Map類型,則需要遞歸調(diào)用exportObject進(jìn)行處理
                   * @param obj
                   * @throws Exception
                   */
                  public void exportObject(Object obj) throws Exception{
                          Exportable exportable=null;
                          String elementName=null;
                          
                          //循環(huán)引用現(xiàn)象處理
                          if (cyclicChecker.contains(obj)){
                                  return;
                          }
                          
                          cyclicChecker.add(obj);
                          
                          //首先處理Collection和Map類型
                          if (obj instanceof Collection){
                                  for(Iterator i=((Collection)obj).iterator();i.hasNext();){
                                          exportObject(i.next());
                                  }
                          }
                          else if (obj instanceof Map){
                                  for(Iterator i=((Map)obj).keySet().iterator();i.hasNext();){
                                          exportObject(i.next());
                                  }
                          }
                          else{

                                  exportable=obj.getClass().getAnnotation(Exportable.class);
                                  //如果obj已經(jīng)被Exportable Annotation修飾過了(注意annotation是具有繼承性的),
                                  //則使用其name作為輸出xml的元素name
                                  if (exportable!=null){
                                          if (exportable.value().length()>0){
                                                  elementName=exportable.value();
                                          }
                                          else{
                                                  elementName=exportable.name();
                                          }
                                  }
                                  //未被修飾或者Exportable Annotation的值為空字符串,
                                  //則使用類名作為輸出xml的元素name
                                  if (exportable==null||elementName.length()==0){
                                          elementName=obj.getClass().getSimpleName();
                                  }
                                  //輸出xml元素頭
                                  System.out.println(getIndent()+"<"+elementName+">");
                                  levelDepth++;
                                  //如果沒有被修飾,則直接輸出其toString()作為元素值
                                  if (exportable==null){
                                          System.out.println(getIndent()+obj.toString());
                                  }
                                  //否則將對(duì)象的成員變量導(dǎo)出為xml
                                  else{
                                          exportFields(obj);
                                  }
                                  levelDepth--;
                                  //輸出xml元素結(jié)尾
                                  System.out.println(getIndent()+"</"+elementName+">");
                                  
                          }
                          cyclicChecker.remove(obj);
                  }
                  
                  public static void main(String[] argv){
                          try{
                                  AddressForTest ad=new AddressForTest("China","Beijing",
                                                  "Beijing","winnerStreet","10");
                                  
                                  ExportToXml test=new ExportToXml();
                                  
                                  ArrayList<String> telephoneList=new ArrayList<String>();
                                  telephoneList.add("66608888");
                                  telephoneList.add("66608889");
                                  
                                  ArrayList<AddressForTest> adList=new ArrayList<AddressForTest>();
                                  adList.add(ad);
                                  
                                  AddressListForTest adl=new AddressListForTest("coolBoy",
                                                  18,telephoneList,adList,"some words");
                                  
                                  test.exportObject(adl);
                          }
                          catch(Exception ex){
                                  ex.printStackTrace();
                          }
                  }
          }


          在ExportToXml類之前的類比較簡單,這里必須說明一下ExportToXml類:此類的核心函數(shù)是exportObject和 exportFields方法,前者輸出對(duì)象的xml信息,后者輸出對(duì)象成員變量的信息。由于對(duì)象類型和成員類型的多樣性,所以采取了以下的邏輯:

          在exportObject方法中,當(dāng)對(duì)象類型為Collection和Map類型時(shí),則需要遞歸調(diào)用exportObject進(jìn)行處理;
          而如果對(duì)象類型不是Collection和Map類型的話,將判斷對(duì)象類是否被Exportable annotation修飾過:
          如果沒有被修飾,則直接輸出<對(duì)象類名>對(duì)象.toString()</對(duì)象類名>作為xml綁定結(jié)果的一部分;
          如果被修飾過,則需要調(diào)用exportFields方法對(duì)對(duì)象的成員變量進(jìn)行xml綁定。

          在exportFields 方法中,首先取出對(duì)象的所有成員,然后獲得被Persisitent annotation修飾的成員。在其后的一句:field.setAccessible(true)是很重要的,因?yàn)閎ean類定義中的成員訪問修飾都 是private,所以為了避免java虛擬機(jī)檢查對(duì)私有成員的訪問權(quán)限,加上這一句是必需的。接著后面的語句便是輸出<成員名>成員值 </成員名>這樣的xml結(jié)構(gòu)。像在exportObject方法中一般,仍然需要判斷成員類型是否為Collection和Map類型,如 果為上述兩種類型之一,則要在exportFields中再次調(diào)用exportObject來處理這個(gè)成員。

          在main方法中,本人編寫了一段演示代碼:建立了一個(gè)由單個(gè)友人地址類(AddressForTest)組成的ArrayList作為通訊錄類(AddressForTest)的成員的通訊錄對(duì)象,并且輸出這個(gè)對(duì)象的xml綁定,運(yùn)行結(jié)果如下:

          清單6:

          <addresslist>
                  <friendName>
                          coolBoy
                  </friendName>
                  <age>
                          18
                  </age>
                  <String>
                          66608888
                  </String>
                  <String>
                          66608889
                  </String>
                  <address>
                          <country>
                                  China
                          </country>
                          <province>
                                  Beijing
                          </province>
                          <city>
                                  Beijing
                          </city>
                          <street>
                                  winnerStreet
                          </street>
                          <doorplate>
                                  10
                          </doorplate>
                  </address>
                  <note>
                          some words
                  </note>
          </addresslist>


          三、APT實(shí)例分析:
          1.何謂APT?
          根 據(jù)sun官方的解釋,APT(annotation processing tool)是一個(gè)命令行工具,它對(duì)源代碼文件進(jìn)行檢測找出其中的annotation后,使用annotation processors來處理annotation。而annotation processors使用了一套反射API并具備對(duì)JSR175規(guī)范的支持。
          annotation processors處理annotation的基本過程如下:首先,APT運(yùn)行annotation processors根據(jù)提供的源文件中的annotation生成源代碼文件和其它的文件(文件具體內(nèi)容由annotation processors的編寫者決定),接著APT將生成的源代碼文件和提供的源文件進(jìn)行編譯生成類文件。
          簡單的和前面所講的annotation 實(shí)例BRFW相比,APT就像一個(gè)在編譯時(shí)處理annotation的javac。而且從sun開發(fā)者的blog中看到,java1.6 beta版中已將APT的功能寫入到了javac中,這樣只要執(zhí)行帶有特定參數(shù)的javac就能達(dá)到APT的功能。

          2.為何使用APT?
          使 用APT主要目的是簡化開發(fā)者的工作量,因?yàn)锳PT可以在編譯程序源代碼的同時(shí),生成一些附屬文件(比如源文件、類文件、程序發(fā)布描述文字等),這些附屬 文件的內(nèi)容也都是與源代碼相關(guān)的。換句話說,使用APT就是代替了傳統(tǒng)的對(duì)代碼信息和附屬文件的維護(hù)工作。使用過hibernate或者beehive等 軟件的朋友可能深有體會(huì)。APT可以在編譯生成代碼類的同時(shí)將相關(guān)的文件寫好,比如在使用beehive時(shí),在代碼中使用annotation聲明了許多 struct要用到的配置信息,而在編譯后,這些信息會(huì)被APT以struct配置文件的方式存放。

          3.如何定義processor?
          A.APT工作過程:
          從 整個(gè)過程來講,首先APT檢測在源代碼文件中哪些annotation存在。然后APT將查找我們編寫的annotation processor factories類,并且要求factories類提供處理源文件中所涉及的annotation的annotation processor。接下來,一個(gè)合適的annotation processors將被執(zhí)行,如果在processors生成源代碼文件時(shí),該文件中含有annotation,則APT將重復(fù)上面的過程直到?jīng)]有新文 件生成。

          B.編寫annotation processors:
          編寫一個(gè)annotation processors需要使用java1.5 lib目錄中的tools.jar提供的以下4個(gè)包:
          com.sun.mirror.apt: 和APT交互的接口;
          com.sun.mirror.declaration: 用于模式化類成員、類方法、類聲明的接口;
          com.sun.mirror.type: 用于模式化源代碼中類型的接口;
          com.sun.mirror.util: 提供了用于處理類型和聲明的一些工具。

          每 個(gè)processor實(shí)現(xiàn)了在com.sun.mirror.apt包中的AnnotationProcessor接口,這個(gè)接口有一個(gè)名為 “process”的方法,該方法是在APT調(diào)用processor時(shí)將被用到的。一個(gè)processor可以處理一種或者多種annotation類 型。
          一個(gè)processor實(shí)例被其相應(yīng)的工廠返回,此工廠為AnnotationProcessorFactory接口的實(shí)現(xiàn)。APT將調(diào)用工 廠類的getProcessorFor方法來獲得processor。在調(diào)用過程中,APT將提供給工廠類一個(gè) AnnotationProcessorEnvironment 類型的processor環(huán)境類對(duì)象,在這個(gè)環(huán)境對(duì)象中,processor將找到其執(zhí)行所需要的每件東西,包括對(duì)所操作的程序結(jié)構(gòu)的參考,與APT通訊 并合作一同完成新文件的建立和警告/錯(cuò)誤信息的傳輸。

          提供工廠類有兩個(gè)方式:通過APT的“-factory”命令行參數(shù)提供,或者讓工廠類在APT的發(fā)現(xiàn)過程中被自動(dòng)定位(關(guān)于發(fā)現(xiàn)過程詳細(xì)介紹請(qǐng)看http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html)。前者對(duì)于一個(gè)已知的factory來講是一種主動(dòng)而又簡單的方式;而后者則是需要在jar文件的META-INF/services目錄中提供一個(gè)特定的發(fā)現(xiàn)路徑:
          在 包含factory類的jar文件中作以下的操作:在META-INF/services目錄中建立一個(gè)名為 com.sun.mirror.apt.AnnotationProcessorFactory 的UTF-8編碼文件,在文件中寫入所有要使用到的factory類全名,每個(gè)類為一個(gè)單獨(dú)行。

          4.一個(gè)簡單的APT實(shí)例分析:
          A.實(shí)例構(gòu)成:
          Review類:定義Review Annotation;
          ReviewProcessorFactory類:生成ReviewProcessor的工廠類;
          ReviewProcessor類:定義處理Review annotation的Processor;
          ReviewDeclarationVisitor類:定義Review annotation聲明訪問者,ReviewProcessor將要使用之對(duì)Class進(jìn)行訪問。
          runapt.bat:定義了使用自定義的ReviewProcessor對(duì)Review類源代碼文件進(jìn)行處理的APT命令行。

          B.Review類:
          清單7:

          package com.bjinfotech.practice.annotation.apt;

          /**
          * 定義Review Annotation
          * @author cleverpig
          *
          */
          public @interface Review {
                  public static enum TypeEnum{EXCELLENT,NICE,NORMAL,BAD};
                  TypeEnum type();
                  String name() default "Review";
          }


          C.ReviewProcessorFactory類:
          清單8:

          package com.bjinfotech.practice.annotation.apt;

          import java.util.Collection;
          import java.util.Set;
          import java.util.Arrays;
          import com.sun.mirror.apt.*;
          import com.sun.mirror.declaration.AnnotationTypeDeclaration;
          import com.sun.mirror.apt.AnnotationProcessorEnvironment;
          //請(qǐng)注意為了方便,使用了靜態(tài)import
          import static java.util.Collections.unmodifiableCollection;
          import static java.util.Collections.emptySet;

          /**
          * 生成ReviewProcessor的工廠類
          * @author cleverpig
          *
          */
          public class ReviewProcessorFactory implements AnnotationProcessorFactory{
                  /**
                   * 獲得針對(duì)某個(gè)(些)類型聲明定義的Processor
                   * @param atds 類型聲明集合
                   * @param env processor環(huán)境
                   */
                  public AnnotationProcessor getProcessorFor(
                                  Set<AnnotationTypeDeclaration> atds,
                                  AnnotationProcessorEnvironment env){
                          return new ReviewProcessor(env);
                  }
                  /**
                   * 定義processor所支持的annotation類型
                   * @return processor所支持的annotation類型的集合
                   */
                  public Collection<String>         supportedAnnotationTypes(){
                          //“*”表示支持所有的annotation類型
                          //當(dāng)然也可以修改為“foo.bar.*”、“foo.bar.Baz”,來對(duì)所支持的類型進(jìn)行修飾
                      return unmodifiableCollection(Arrays.asList("*"));
              }
                  
                  /**
                   * 定義processor支持的選項(xiàng)
                   * @return processor支持選項(xiàng)的集合
                   */
                  public Collection<String>         supportedOptions(){
                          //返回空集合
                      return emptySet();
              }
                  
                  public static void main(String[] argv){
                          System.out.println("ok");
                  }
          }


          D.ReviewProcessor類:
          清單9:

          package com.bjinfotech.practice.annotation.apt;

          import com.sun.mirror.apt.AnnotationProcessor;
          import com.sun.mirror.apt.AnnotationProcessorEnvironment;
          import com.sun.mirror.declaration.TypeDeclaration;
          import com.sun.mirror.util.DeclarationVisitors;
          import com.sun.mirror.util.DeclarationVisitor;

          /**
          * 定義Review annotation的Processor
          * @author cleverpig
          *
          */
          public class ReviewProcessor implements AnnotationProcessor{
                  //Processor所工作的環(huán)境
                  AnnotationProcessorEnvironment env=null;
                  
                  /**
                   * 構(gòu)造方法
                   * @param env 傳入processor環(huán)境
                   */
                  public ReviewProcessor(AnnotationProcessorEnvironment env){
                          this.env=env;
                  }
                  
                  /**
                   * 處理方法:查詢processor環(huán)境中的類型聲明,
                   */
                  public void process(){
                          //查詢processor環(huán)境中的類型聲明
                          for(TypeDeclaration type:env.getSpecifiedTypeDeclarations()){
                                  //返回對(duì)類進(jìn)行掃描、訪問其聲明時(shí)使用的DeclarationVisitor,
                                  //傳入?yún)?shù):new ReviewDeclarationVisitor(),為掃描開始前進(jìn)行的對(duì)類聲明的處理
                                  //        DeclarationVisitors.NO_OP,表示在掃描完成時(shí)進(jìn)行的對(duì)類聲明不做任何處理
                                  DeclarationVisitor visitor=DeclarationVisitors.getDeclarationScanner(
                                                  new ReviewDeclarationVisitor(),DeclarationVisitors.NO_OP);
                                  //應(yīng)用DeclarationVisitor到類型
                                  type.accept(visitor);
                          }
                  }
          }


          E.ReviewDeclarationVisitor類:
          清單10:

          package com.bjinfotech.practice.annotation.apt;

          import com.sun.mirror.util.*;
          import com.sun.mirror.declaration.*;

          /**
          * 定義Review annotation聲明訪問者
          * @author cleverpig
          *
          */
          public class ReviewDeclarationVisitor extends SimpleDeclarationVisitor{
                  /**
                   * 定義訪問類聲明的方法:打印類聲明的全名
                   * @param cd 類聲明對(duì)象
                   */
                  public void visitClassDeclaration(ClassDeclaration cd){
                          System.out.println("獲取Class聲明:"+cd.getQualifiedName());
                  }
                  
                  public void visitAnnotationTypeDeclaration(AnnotationTypeDeclaration atd){
                          System.out.println("獲取Annotation類型聲明:"+atd.getSimpleName());
                  }
                  
                  public void visitAnnotationTypeElementDeclaration(AnnotationTypeElementDeclaration aed){
                          System.out.println("獲取Annotation類型元素聲明:"+aed.getSimpleName());
                  }
          }


          F.runapt.bat文件內(nèi)容如下:
          清單11:

          E:
          rem 項(xiàng)目根目錄
          set PROJECT_ROOT=E:\eclipse3.1RC3\workspace\tigerFeaturePractice
          rem 包目錄路徑
          set PACKAGEPATH=com\bjinfotech\practice\annotation\apt
          rem 運(yùn)行根路徑
          set RUN_ROOT=%PROJECT_ROOT%\build
          rem 源文件所在目錄路徑
          set SRC_ROOT=%PROJECT_ROOT%\test
          rem 設(shè)置Classpath
          set CLASSPATH=.;%JAVA_HOME%;%JAVA_HOME%/lib/tools.jar;%RUN_ROOT%

          cd %SRC_ROOT%\%PACKAGEPATH%
          apt -nocompile -factory com.bjinfotech.practice.annotation.apt.ReviewProcessorFactory  ./*.java


          四、參考資源:
          http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html
          作者的Blog:http://blog.matrix.org.cn/page/cleverpig


          五、源代碼下載:
          [下載文件]



          -------------------------------------------
          1、引入

          l         編程的一個(gè)最新趨勢,尤其是 Java 編程,就是使用元數(shù)據(jù)

          l         元數(shù)據(jù)可以用于創(chuàng)建文檔,跟蹤代碼中的依賴性,甚至執(zhí)行基本編譯時(shí)檢查

          l         許多元數(shù)據(jù)工具(如 Xdoclet)將這些功能添加到核心 Java 語言中,暫時(shí)成為 Java 編程功能的一部分

          l         Javadoc是元數(shù)據(jù)工具,但除了生成文檔之外,沒有固定、實(shí)用、標(biāo)準(zhǔn)化的方式將數(shù)據(jù)用于其他用途,而且HTML代碼經(jīng)常混入到Javadoc輸出中,更進(jìn)一步降低了其用于任何其它目的的價(jià)值

          l         JSR 175Java編程語言的元數(shù)據(jù)工具,為將元數(shù)據(jù)合并到核心 Java 語言中提供了正式理由和說明

          l         Tiger 增加了Annotation的新功能,將一個(gè)更通用的元數(shù)據(jù)工具合并到核心 Java 語言中

          l         Annotation是可以添加到代碼中的修飾符,可以用于包聲明、類型聲明、構(gòu)造函數(shù)、方法、域變量、參數(shù)和變量

          l         Tiger包含內(nèi)置的Annotation,還支持自己編寫的定制Annotation

          l         本部分將概述元數(shù)據(jù)的優(yōu)點(diǎn),并介紹Tiger的內(nèi)置Annotation

           

          2、元數(shù)據(jù)的價(jià)值

          一般來說,元數(shù)據(jù)的好處分為三類:文檔編制、編譯器檢查和代碼分析

          1)文檔編制

          l         代碼級(jí)文檔最常被引用,但對(duì)于將元數(shù)據(jù)添加到 Java 語言中來說,文檔編制可能是最不相關(guān)的理由

          l         因?yàn)?/span>Javadoc已經(jīng)提供了非常容易理解和健壯的方法來文檔化代碼

          2)編譯時(shí)檢查

          l         元數(shù)據(jù)更重要的優(yōu)點(diǎn)是編譯器可以使用它來執(zhí)行基本的編譯時(shí)檢查

          l         具體情況請(qǐng)參看后面介紹的Tiger內(nèi)置Annotation@Override

          3)代碼分析

          l         元數(shù)據(jù)工具的最好功能就是可以使用額外數(shù)據(jù)來分析代碼

          l         簡單的案例就是:許多時(shí)候,方法的參數(shù)類型或返回類型實(shí)際上不是該方法想要的類型;例如,參數(shù)類型可能是Object,但方法可能僅使用Integer,這在覆蓋超類的方法時(shí)很容易發(fā)生;元數(shù)據(jù)可以指示代碼分析工具:雖然參數(shù)類型是 Object,但 Integer 才是真正需要的

          l         復(fù)雜的案例就是:即使是簡單EJB系統(tǒng)中也具有很強(qiáng)的依賴性和復(fù)雜性,要具有 HomeRemote接口,以及本地的Home Remote接口,以及一個(gè)實(shí)現(xiàn)類,保持所有這些類同步非常困難;好的工具(如XDoclet)可以管理所有這些依賴性,并確保這些沒有“代碼級(jí)”聯(lián)系,但有“邏輯級(jí)”聯(lián)系的類保持同步;元數(shù)據(jù)在這里確實(shí)可以發(fā)揮它的作用

           

          3Annotation基礎(chǔ)

          l         Annotation的格式是:@Annotation

          l         Annotation需要數(shù)據(jù)時(shí),通過name=value的形式提供

          l         代碼中可以用很多Annotation,有些Annotation會(huì)具有相同的Annotation類型

          l         Annotation類型和Annotation的概念類似于類和對(duì)象的概念

          l         Annotation有三種基本種類:

          Ø         標(biāo)記Annotation:只有Annotation名,不包含數(shù)據(jù),如@MarkerAnnotation

          Ø         單值Annotation:只有單一的數(shù)據(jù),可以簡化name=value的形式為value形式,如@SingleValueAnnotation("my data")

          Ø         完整格式的Annotation:有多個(gè)數(shù)據(jù)成員,如@FullAnnotation(var1="data value 1", var2="data value 2", var3="data value 3")

          l         可以使用花括號(hào)向Annotation變量提供值數(shù)組,如

          @TODOItems({    // Curly braces indicate an array of values is being supplied
            @TODO(
              severity=TODO.CRITICAL,
              item="Add functionality to calculate the mean of the student's grades",
              assignedTo="Brett McLaughlin"
            ),
            @TODO(
              severity=TODO.IMPOTANT,
              item="Print usage message to screen if no command-line flags specified",
              assignedTo="Brett McLaughlin"
            ),
            @TODO(
              severity=TODO.LOW,
              item="Roll a new website page with this class's new features",
              assignedTo="Jason Hunter"
            )
          })

           

          4Tiger內(nèi)置Annotation

          1@Override

          l         @Override只用于方法,指明改方法覆蓋超類中的對(duì)應(yīng)方法

          l         簡單例子:

          public class OverrideTester {
           
                 public OverrideTester() {
                 }
           
                 @Override public String toString() {
                        return super.toString() + " [Override Tester Implementation]";
                 }
           
                 @Override public int hashCode() {
                        return toString().hashCode();
                 }
          }

          l         @Override可以檢查輸入錯(cuò)誤導(dǎo)致無法覆蓋超類方法的問題,例如hashCode()錯(cuò)誤的輸入為hasCode(),在編譯時(shí)就會(huì)報(bào)錯(cuò):

          The method hasCode() of type OverrideTester must override a superclass method

          l         這個(gè)便捷的小功能將幫助快速捕獲打字錯(cuò)誤

          2@Deprecated

          l         同樣只用于方法,指明該方法不應(yīng)該再使用了

          l         簡單例子:

          public class DeprecatedClass {
           
                 @Deprecated public void doSomething() {
                        System.out.println("Deprecated method!");
                        // some code
                 }
           
                 public void doSomethingElse() {
                        // This method presumably does what doSomething() does, but better
                 }
          }

          l         單獨(dú)編譯正常通過,如果通過覆蓋或調(diào)用Deprecated方法,編譯器會(huì)給出警告信息

          l         注:本人在Eclipse 3.1M4環(huán)境中測試,根本不起作用(即使是改了編譯參數(shù),why?),在命令行下使用-Xlint:deprecated參數(shù),JAVAC只給出警告信息,編譯還是通過的

          3@SuppressWarnings

          l         Tiger的泛型功能使得編譯器對(duì)類型的安全性進(jìn)行檢查,特別是Java集合,如下面的例子:

                 public void nonGenericsMethod() {
                        List wordList = new ArrayList(); // no typing information on the List
                        wordList.add("foo"); // causes error on list addition
                 }

          l         編譯器會(huì)給出下面的警告信息:

          Type safety: The method add(Object) belongs to the raw type List. References to generic 
           type List<E> should be parameterized

          l         這對(duì)于Tiger的代碼是很有幫助的,但對(duì)于JDK1.4及以前版本,不斷的收到無關(guān)的警告信息是很煩人的

          l         可以使用@SuppressWarnings來阻止指定類型的警告信息,如:

                 @SuppressWarnings(value = { "unchecked" }) 
                 public void nonGenericsMethod() {
                        List wordList = new ArrayList(); // no typing information on the List
                        wordList.add("foo"); // causes error on list addition
                 }

          l         傳遞給@SuppressWarnings的類型值是一個(gè)數(shù)組,因此可以同時(shí)阻止多種類型的警告信息

          l         類型值是由編譯器廠商所指定的,所以上面的例子我在Eclipse 3.1M4環(huán)境和命令行中測試,都不起作用,大概是類型值沒有指定對(duì)吧


          ---------------------------------------

          1、自定義Annotation類型

          1)定義Annotation類型

          l         使用@interface聲明Annotation類型

          public @interface InProgress {
           
          }

          l         使用Annotation類型

          public class TestAnnotation {
                 @InProcess
                 public void test() {
                   
                 }
          }

          l         如果Annotation類型和使用它的類不在相同的包中,可以import Annotation類型,以便直接使用 @InProgress

          2)添加成員

          l         Annotation類型可以有成員變量,以提供有用的信息

          l         定義數(shù)據(jù)成員不需要定義gettersetter方法,只需要定義一個(gè)以成員名稱命名的方法,并指定返回類型為需要的數(shù)據(jù)類型

          l         簡單的例子:

          public @interface TODO {
                 String value();
          }

          l         使用帶成員的Annotation類型:

          public class TestAnnotation {
                 @InProcess
                 @TODO("Need to finish this method later")
                 public void test() {
                   
                 }
          }

          3)設(shè)置缺省值

          l         要為Annotation類型的成員設(shè)置缺省值,需要在聲明成員時(shí)使用default關(guān)鍵字:

          public @interface GroupTODO {
                 public enum Severity {
                        CRITICAL, IMPORTANT, TRIVIAL, DOCUMENTATION
                 };
           
                 Severity severity() default Severity.IMPORTANT;
                 String item();
                 String assignedTo();
                 String dateAssigned();
          }

          l         當(dāng)然,缺省值的類型必須與成員變量聲明的類型完全相同

          l         下面是使用缺省值的例子:

          public class TestAnnotation {
                 @InProcess
                 @GroupTODO(
                        item="Need to finish this method later",
                        assignedTo="nelson_tu",
                        dateAssigned="2005/02/05"
                 )
                 public void test() {
                   
                 }
          }

          l         下面是改寫缺省值的例子:

          public class TestAnnotation {
                 @InProcess
                 //@TODO("Need to finish this method later")
                 @GroupTODO(
                        severity=GroupTODO.Severity.DOCUMENTATION,
                        item="Need to finish this method later",
                        assignedTo="nelson_tu",
                        dateAssigned="2005/02/05"
                 )
                 public void test() {
                   
                 }
          }

           

          2、元Annotation

          l         Annotation就是AnnotationAnnotationJDK5提供了4種預(yù)定義的元Annotation

          1@Target

          l         @Target指定Annotation類型可以應(yīng)用的程序元素,以便在其它程序元素中誤用Annotation類型

          l         程序元素的類型由java.lang.annotation.ElementType枚舉類定義:

          package java.lang.annotation;
           
          public enum ElementType {
            TYPE,          // Class, interface, or enum (but not annotation)
            FIELD,         // Field (including enumerated values)
            METHOD,        // Method (does not include constructors)
            PARAMETER,             // Method parameter
            CONSTRUCTOR,           // Constructor
            LOCAL_VARIABLE, // Local variable or catch clause
            ANNOTATION_TYPE,       // Annotation Types (meta-annotations)
            PACKAGE        // Java package
          }

          l         下面是使用@Target的例子:

          @Target({ElementType.TYPE,
              ElementType.METHOD,
              ElementType.CONSTRUCTOR,
              ElementType.ANNOTATION_TYPE})
          public @interface TODO {
                 String value();
          }

          2@Retention

          l         @Retention Java 編譯器處理Annotation類型的方式有關(guān)

          l         這些方式由java.lang.annotation.RetentionPolicy 枚舉類定義:

          package java.lang.annotation;
           
          public enum RetentionPolicy {
            SOURCE,       // Annotation is discarded by the compiler
            CLASS,       // Annotation is stored in the class file, but ignored by the VM
            RUNTIME       // Annotation is stored in the class file and read by the VM
          }

          l         使用@Retention的例子參看后面的@Documented

          3@Documented

          l         @Documented指明需要在Javadoc中包含Annotation(缺省是不包含的)

          l         下面是一個(gè)使用@Documented的例子:

          @Documented
          @Retention(RetentionPolicy.RUNTIME)
          public @interface InProcess {
           
          }

          l         使用@Documented的一個(gè)技巧就是指定保持性策略為RetentionPolicy.RUNTIME:這樣,Annotation就會(huì)保留在編譯后的類文件中并且由虛擬機(jī)加載,然后Javadoc就可以抽取出Annotation,添加到類的HTML文檔中

          4@Inherited

          l         @Inherited最復(fù)雜、使用最少、也最容易造成混淆的一個(gè)

          l         假設(shè)使用@InProgress 標(biāo)記一個(gè)正在開發(fā)的類,只要正確應(yīng)用@DocumentedAnnotation信息就會(huì)出現(xiàn)在Javadoc中;現(xiàn)在要編寫一個(gè)新類,擴(kuò)展那個(gè)正在開發(fā)的類,那么使用子類,或者查看它的文檔,根本沒法表明還有什么地方?jīng)]有完成;而本來是希望@InProgress Annotation信息會(huì)被帶到子類中,這就需要使用@Inherited

          l         下面是這樣的例子:

          @Documented
          @Inherited
          @Retention(RetentionPolicy.RUNTIME)
          public @interface InProcess {
           
          }

           



          posted on 2007-07-22 22:42 dyerac in java... 閱讀(839) 評(píng)論(1)  編輯  收藏 所屬分類: JavaSE
          評(píng)論:
          • # 《中國科技博覽》征稿函  劉越 Posted @ 2008-10-24 09:47

            《中國科技博覽》征稿函

            中國核心期刊(遴選)數(shù)據(jù)庫收錄期刊   中國學(xué)術(shù)期刊中國(光盤版)收錄期刊
            統(tǒng)一刊號(hào): CN11-4450/T ISSN1009-914X
            (國家級(jí)學(xué)術(shù)期刊 科技論文交流平臺(tái))
            《中國科技博覽》雜志是由國務(wù)院國有資產(chǎn)監(jiān)督管理委員會(huì)(國資委)主管,中國包裝總公司主辦的國家級(jí)學(xué)術(shù)期刊;。(國內(nèi)刊號(hào): CN11-4450/T 國際刊號(hào): ISSN1009-914X )本刊被《中國核心期刊(遴選)數(shù)據(jù)庫》《中國學(xué)術(shù)期刊(光盤版)》《萬方數(shù)據(jù)數(shù)字化期刊群》《中文科技期刊數(shù)據(jù)庫》等網(wǎng)絡(luò)媒體全文收錄,國內(nèi)外深有影響。旨在推廣科教新理論、新經(jīng)驗(yàn),為廣大教育、科研工作者提供學(xué)術(shù)交流平臺(tái),推動(dòng)科技、教育事業(yè)發(fā)展。
            【辦刊宗旨】
            本刊堅(jiān)持國家科技創(chuàng)新、教育創(chuàng)新方針,傳播科技理念、報(bào)道科技動(dòng)態(tài)、倡導(dǎo)科技創(chuàng)新、促進(jìn)科技進(jìn)步;廣泛探討交流科技、教育工作成果;多方位、多層次介紹科教創(chuàng)新的前沿性內(nèi)容。
            【主要欄目】
            工程技術(shù)、工業(yè)技術(shù)、教學(xué)研究、建筑科學(xué)、IT技術(shù)、電子商務(wù)、資源與環(huán)境、財(cái)會(huì)審計(jì)、信息科學(xué)、學(xué)術(shù)論壇、行業(yè)科技、創(chuàng)新與實(shí)踐、經(jīng)營管理、經(jīng)濟(jì)綜述、圖書館論壇等相關(guān)欄目及內(nèi)容.
            【征稿對(duì)象】
            全國教科研工作者、廣大教師、各級(jí)科技與教育管理部門領(lǐng)導(dǎo)、科研院所、科技教育人員、科教領(lǐng)域管理人員、各大院校的在讀博士生、碩士生及社會(huì)各界關(guān)心科教工作的人士。
            【來稿須知】
            ① 稿件應(yīng)具有科學(xué)性、先進(jìn)性和實(shí)用性,論點(diǎn)明確、論據(jù)可靠、數(shù)據(jù)準(zhǔn)確、邏輯嚴(yán)謹(jǐn)、文字通順。
            ② 論文2200—6000字符數(shù)為宜,來稿請(qǐng)使用word排版,并請(qǐng)注明作者姓名、單位、通訊地址、郵編、電子信箱、聯(lián)系電話等,本刊歡迎網(wǎng)上投稿。本刊已被《中國核心期刊(遴選)數(shù)據(jù)
            ③ 論文的基本要素齊全,文章標(biāo)題、作者單位、作者姓名、關(guān)鍵詞、摘要、結(jié)語、參考文獻(xiàn)等。
            ④ 所投稿件請(qǐng)保證文章版權(quán)的獨(dú)立性,無抄襲、署名排序無爭議、文責(zé)自負(fù),請(qǐng)勿一稿多投!
            *來稿無論我刊選用與否,都會(huì)在5個(gè)工作日內(nèi)將審理結(jié)果盡快通知作者,作者也可來電查詢,以免影響正常發(fā)表。
            投稿信箱: zgkjblliu@yahoo.com.cn
            【本刊誠聘特約編委、組稿編輯】
            為不斷提高刊物學(xué)術(shù)水平,我刊現(xiàn)面向全國教育科研系統(tǒng)招聘編委及組稿編輯,負(fù)責(zé)部分重點(diǎn)稿件的編審并幫助所在單位、系統(tǒng)、地區(qū)的教科研工作者解決學(xué)術(shù)論文的寫作和在本刊的發(fā)表事宜。
            權(quán)利待遇:發(fā)特約編委證書;優(yōu)先在本刊刊發(fā)學(xué)術(shù)論文;本刊將會(huì)酌情付給酬金。
            詳情請(qǐng)來電來函咨詢:010-51347973
            E-mail:zgkjblliu@yahoo.com.cn
            【有關(guān)事宜】
            優(yōu)秀稿件我們會(huì)提交參選我社論文評(píng)優(yōu)活動(dòng),獲獎(jiǎng)作品頒布發(fā)榮譽(yù)證書。
            【網(wǎng)上查證】
            登陸以下官方網(wǎng)站可對(duì)《中國科技博覽》進(jìn)行網(wǎng)上查詢。
            北京市新聞出版局:www.bjppb.gov.cn
            中國新聞總署: www.gapp.gov.cn/
            聯(lián) 系 人:劉越(老師)
            電 話:010--51347973 13041201895
            投稿信箱: zgkjblliu@yahoo.com.cn (投稿專用)
            工 作Q Q: 793021885
            雜志社地址:北京市東城區(qū)興化路9號(hào)院大樓516室
            郵 編:100013


              回復(fù)  更多評(píng)論   

           
          Copyright © dyerac in java... Powered by: 博客園 模板提供:滬江博客
          主站蜘蛛池模板: 云和县| 四子王旗| 兰州市| 宜宾县| 油尖旺区| 新绛县| 水富县| 江陵县| 景德镇市| 平顺县| 潮安县| 清苑县| 诏安县| 潜江市| 浪卡子县| 会宁县| 东阳市| 西峡县| 九江县| 建昌县| 宜城市| 锡林郭勒盟| 新巴尔虎右旗| 根河市| 浦东新区| 淮南市| 静海县| 叙永县| 万载县| 康乐县| 始兴县| 基隆市| 巢湖市| 延边| 林甸县| 嘉峪关市| 沛县| 广东省| 毕节市| 福贡县| 东乌|