dyerac |
|
|||
dyerac In Java |
公告
日歷
統(tǒng)計(jì)
導(dǎo)航常用鏈接留言簿(5)隨筆分類(49)
隨筆檔案(36)
文章分類(11)文章檔案(10)相冊(cè)dyerac搜索積分與排名
最新隨筆
最新評(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: /** 代碼中只定義了一個(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( B:當(dāng)聲明一個(gè)沒有成員的annotation類型聲明時(shí),可使用以下方式: /**
清單4:
@Preliminary public class TimeTravel { ... }
清單5:
/**
清單6:
@Copyright("2002
結(jié)合上面所講的,我們?cè)谶@里建立一個(gè)簡單的基于annotation測試框架。首先我們需要一個(gè)annotation類型來表示某個(gè)方法是一個(gè)應(yīng)該被測試工具運(yùn)行的測試方法。
清單7:
import java.lang.annotation.*;
在上面的代碼中,@Retention(RetentionPolicy.RUNTIME)這個(gè)meta-annotation表示了此類型的 annotation將被虛擬機(jī)保留使其能夠在運(yùn)行時(shí)通過反射被讀取。而@Target(ElementType.METHOD)表示此類型的 annotation只能用于修飾方法聲明。
下面是一個(gè)簡單的程序,其中部分方法被上面的annotation所標(biāo)注:
清單8:
public class Foo {
下面文字表示了如何運(yùn)行這個(gè)基于annotation的測試工具:
清單9:
$ java RunTests Foo
根據(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;
下面是一個(gè)使用annotation進(jìn)行方法測試的sample:
AnnotationDefineForTestFunction類型定義如下:
清單11: package com.bjinfotech.practice.annotation;
清單12: 版權(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:
B.Exportable類: 清單2:
C.AddressForTest類: 清單3:
D.AddressListForTest類: 清單4:
E.ExportToXml類: 清單5:
在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:
三、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:
C.ReviewProcessorFactory類: 清單8:
D.ReviewProcessor類: 清單9:
E.ReviewDeclarationVisitor類: 清單10:
F.runapt.bat文件內(nèi)容如下: 清單11:
四、參考資源: 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 175,Java編程語言的元數(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ù)雜性,要具有 Home和Remote接口,以及本地的Home 和Remote接口,以及一個(gè)實(shí)現(xiàn)類,保持所有這些類同步非常困難;好的工具(如XDoclet)可以管理所有這些依賴性,并確保這些沒有“代碼級(jí)”聯(lián)系,但有“邏輯級(jí)”聯(lián)系的類保持同步;元數(shù)據(jù)在這里確實(shí)可以發(fā)揮它的作用 3、Annotation基礎(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"
)
})
4、Tiger內(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ù)成員不需要定義getter和setter方法,只需要定義一個(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就是Annotation的Annotation,JDK5提供了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 這些方式由 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)用@Documented,Annotation信息就會(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 {
}
評(píng)論:
|
![]() |
|
Copyright © dyerac in java... | Powered by: 博客園 模板提供:滬江博客 |