Java Annotation详解
http://djjchobits.iteye.com/blog/569000
元數(shù)據(jù)的作用
如果要對于元數(shù)據(jù)的作用進(jìn)行分類,目前還沒有明確的定義,不過我們可以根據(jù)它所起的作用,大致可分為三類:
l ???????? 編寫文檔:通過代碼里標(biāo)識的元數(shù)據(jù)生成文檔。
l ???????? 代碼分析:通過代碼里標(biāo)識的元數(shù)據(jù)對代碼進(jìn)行分析。
l ???????? 編譯檢查:通過代碼里標(biāo)識的元數(shù)據(jù)讓編譯器能實(shí)現(xiàn)基本的編譯檢查。
?
基本內(nèi)置注釋
??? @Override 注釋能實(shí)現(xiàn)編譯時(shí)檢查,你可以為你的方法添加該注釋,以聲明該方法是用于覆蓋父類中的方法。如果該方法不是覆蓋父類的方法,將會(huì)在編譯時(shí)報(bào)錯(cuò)。例如我們?yōu)槟愁愔貙憈oString() 方法卻寫成了tostring() ,并且我們?yōu)樵摲椒ㄌ砑恿?#64;Override 注釋;
???? @Deprecated 的作用是對不應(yīng)該在使用的方法添加注釋,當(dāng)編程人員使用這些方法時(shí),將會(huì)在編譯時(shí)顯示提示信息,它與javadoc 里的 @deprecated 標(biāo)記有相同的功能,準(zhǔn)確的說,它還不如javadoc @deprecated ,因?yàn)樗恢С謪?shù),
注意:要了解詳細(xì)信息,請使用 -Xlint:deprecation 重新編譯。
??? @SuppressWarnings 與前兩個(gè)注釋有所不同,你需要添加一個(gè)參數(shù)才能正確使用,這些參數(shù)值都是已經(jīng)定義好了的,我們選擇性的使用就好了,參數(shù)如下:
?
deprecation?? 使用了過時(shí)的類或方法時(shí)的警告
unchecked? 執(zhí)行了未檢查的轉(zhuǎn)換時(shí)的警告,例如當(dāng)使用集合時(shí)沒有用泛型 (Generics) 來指定集合保存的類型
fallthrough?? 當(dāng) Switch 程序塊直接通往下一種情況而沒有 Break 時(shí)的警告
path?? 在類路徑、源文件路徑等中有不存在的路徑時(shí)的警告
serial 當(dāng)在可序列化的類上缺少 serialVersionUID 定義時(shí)的警告
finally??? 任何 finally 子句不能正常完成時(shí)的警告
all 關(guān)于以上所有情況的警告
?
注意:要了解詳細(xì)信息,請使用 -Xlint:unchecked 重新編譯。
?
定制注釋類型
??? 好的,讓我們創(chuàng)建一個(gè)自己的注釋類型(annotation type )吧。它類似于新創(chuàng)建一個(gè)接口類文件,但為了區(qū)分,我們需要將它聲明為@interface, 如下例:
public @interface NewAnnotation {
?
}
?
使用定制的注釋類型
??? 我們已經(jīng)成功地創(chuàng)建好一個(gè)注釋類型NewAnnotation ,現(xiàn)在讓我們來嘗試使用它吧,如果你還記得本文的第一部分,那你應(yīng)該知道他是一個(gè)標(biāo)記注釋,使用也很容易,如下例:
public class AnnotationTest {
?
??? @NewAnnotation
??? public static void main(String[] args) {
???
??? }
}
?
添加變量
??? J2SE 5.0 里,我們了解到內(nèi)置注釋@SuppressWarnings() 是可以使用參數(shù)的,那么自定義注釋能不能定義參數(shù)個(gè)數(shù)和類型呢?答案是當(dāng)然可以,但參數(shù)類型只允許為基本類型、String 、Class 、枚舉類型等,并且參數(shù)不能為空。我們來擴(kuò)展NewAnnotation ,為之添加一個(gè)String 類型的參數(shù),示例代碼如下:
public @interface NewAnnotation {
?
??? String value();
}
??? 使用該注釋的代碼如下:正如你所看到的,該注釋的使用有兩種寫法,這也是在之前的文章里所提到過的。如果你忘了這是怎么回事,那就再去翻翻吧。
public class AnnotationTest {
?
??? @NewAnnotation("Just a Test.")
??? public static void main(String[] args) {
??????? sayHello();
??? }
???
??? @NewAnnotation(value="Hello NUMEN.")
??? public static void sayHello() {
??????? // do something
??? }
}
?
為變量賦默認(rèn)值
??? 我們對Java 自定義注釋的了解正在不斷的增多,不過我們還需要更過,在該條目里我們將了解到如何為變量設(shè)置默認(rèn)值,我們再對NewAnnotaion 進(jìn)行修改,看看它會(huì)變成什么樣子,不僅參數(shù)多了幾個(gè),連類名也變了。但還是很容易理解的,我們先定義一個(gè)枚舉類型,然后將參數(shù)設(shè)置為該枚舉類型,并賦予默認(rèn)值。
public @interface Greeting {
?
??? public enum FontColor {RED, GREEN, BLUE};
?
??? String name();
?
??? String content();
???
??? FontColor fontColor() default FontColor.BLUE;
}
?
限定注釋使用范圍
??? 當(dāng)我們的自定義注釋不斷的增多也比較復(fù)雜時(shí),就會(huì)導(dǎo)致有些開發(fā)人員使用錯(cuò)誤,主要表現(xiàn)在不該使用該注釋的地方使用。為此,Java 提供了一個(gè)ElementType 枚舉類型來控制每個(gè)注釋的使用范圍,比如說某些注釋只能用于普通方法,而不能用于構(gòu)造函數(shù)等。下面是Java 定義的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
}
??? 下面我們來修改Greeting 注釋,為之添加限定范圍的語句,這里我們稱它為目標(biāo)(Target )使用方法也很簡單,如下:
?
@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })
public @interface Greeting {
}
正如上面代碼所展示的,我們只允許Greeting 注釋標(biāo)注在普通方法和構(gòu)造函數(shù)上,使用在包申明、類名等時(shí),會(huì)提示錯(cuò)誤信息。
?
注釋保持性策略
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
}
??? RetentionPolicy 的使用方法與ElementType 類似,簡單代碼示例如下:
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })
?
文檔化功能
??? Java 提供的Documented 元注釋跟Javadoc 的作用是差不多的,其實(shí)它存在的好處是開發(fā)人員可以定制Javadoc 不支持的文檔屬性,并在開發(fā)中應(yīng)用。它的使用跟前兩個(gè)也是一樣的,簡單代碼示例如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })
public @interface Greeting {
}
?
值得大家注意的是,如果你要使用@Documented 元注釋,你就得為該注釋設(shè)置RetentionPolicy.RUNTIME 保持性策略。為什么這樣做,應(yīng)該比較容易理解,這里就不提了。
?
標(biāo)注繼承
繼承應(yīng)該是Java 提供的最復(fù)雜的一個(gè)元注釋了,它的作用是控制注釋是否會(huì)影響到子類,簡單代碼示例如下:
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })
public @interface Greeting {
}
?
讀取注釋信息
??? 當(dāng)我們想讀取某個(gè)注釋信息時(shí),我們是在運(yùn)行時(shí)通過反射來實(shí)現(xiàn)的,如果你對元注釋還有點(diǎn)印象,那你應(yīng)該記得我們需要將保持性策略設(shè)置為RUNTIME ,也就是說只有注釋標(biāo)記了@Retention(RetentionPolicy.RUNTIME) 的,我們才能通過反射來獲得相關(guān)信息,下面的例子我們將沿用前面幾篇文章中出現(xiàn)的代碼,并實(shí)現(xiàn)讀取AnnotationTest 類所有方法標(biāo)記的注釋并打印到控制臺。好了,我們來看看是如何實(shí)現(xiàn)的吧:
public class AnnotationIntro {
?
??? public static void main(String[] args) throws Exception {
?
??????? Method[] methods = Class.forName(
??????????????? "com.gelc.annotation.demo.customize.AnnotationTest")
??????????????? .getDeclaredMethods();
??????? Annotation[] annotations;
?
??????? for (Method method : methods) {
??????????? annotations = method.getAnnotations();
??????????? for (Annotation annotation : annotations) {
??????????????? System.out.println(method.getName() + " : "
??????????????????????? + annotation.annotationType().getName());
??????????? }
?
********************************************************************************
?
Annotation(注解)
Annotation對于程序運(yùn)行沒有影響,它的目的在于對編譯器或分析工具說明程序的某些信息,您可以
 在包,類,方法,域成員等加上Annotation.每一個(gè)Annotation對應(yīng)于一個(gè)實(shí)際的Annotation類型.
1??限定Override父類方法@Override
 ??java.lang.Override是J2SE5.0中標(biāo)準(zhǔn)的Annotation類型之一,它對編譯器說明某個(gè)方法必須
 ??是重寫父類中的方法.編譯器得知這項(xiàng)信息后,在編譯程序時(shí)如果發(fā)現(xiàn)被@Override標(biāo)示的方法
 ??并非重寫父類中的方法,就會(huì)報(bào)告錯(cuò)誤.
 ??例,如果在定義新類時(shí)想要重寫Object類的toString()方法,可能會(huì)寫成這樣:
 ??public class CustomClass{
 ????public String ToString(){
 ??????return "customObject";
 ????}
 ??}
 ??在編寫toString()方法時(shí),因?yàn)檩斎脲e(cuò)誤或其他的疏忽,將之寫成ToString()了,編譯這個(gè)類時(shí)
 ??并不會(huì)出現(xiàn)任何的錯(cuò)誤,編譯器不會(huì)知道您是想重寫toString()方法,只會(huì)以為是定義了一個(gè)新
 ??的ToString()方法.
 ??可以使用java.lang.Override這個(gè)Annotation類型,在方法上加一個(gè)@Override的Annotation
 ??這可以告訴編譯器現(xiàn)在定義的這個(gè)方法,必須是重寫父類中的同包方法.
 ??public class CustomClass{
 ????@Override
 ????public String toString(){
 ??????return "coustomObject";
 ????}
 ??}
 ??java.lang.Override是一個(gè)Marker Annotation,簡單地說就是用于標(biāo)示的Annotation,Annotation
 ??名稱本身表示了要給工具程序的信息。
 ??
 ??Annotation類型與Annotation實(shí)際上是有區(qū)分的,Annotation是Annotation類型的實(shí)例,例如
 ??@Override是個(gè)Annotation,它是java.lang.Override類型的一個(gè)實(shí)例,一個(gè)文件中可以有很多
 ??個(gè)@Override,但它們都是屬于java.lang.Override類型。
 ??
 2??標(biāo)示方法為Deprecated @Deprecated
 ??java.lang.Deprecated也是J2SE5.0中標(biāo)準(zhǔn)的Annotation類型之一。它對編譯器說明某個(gè)方法已經(jīng)不
 ??建議使用。如果有開發(fā)人員試圖使用或重寫被@Deprecated標(biāo)示的方法,編譯器必須提出警告信息。
 ??例:
 ??public class Something{
 ????@Deprecated
 ????public Something getSomething(){
 ??????return new Something();
 ????}
 ??}
 ??如果有人試圖在繼承這個(gè)類后重寫getSomething()方法,或是在程序中調(diào)用getSomething()方法,
 ??則編譯時(shí)會(huì)有警告出現(xiàn)。
 ??java.lang.Deprecated也是一個(gè)Marker Annotation簡單地說就是用于標(biāo)示。
 ??
 3??抑制編譯器警告 @SuppressWarnings
 ??java.lang.SuppressWarnings也是J2SE5.0中標(biāo)準(zhǔn)的Annotation類型之一,它對編譯器說明某個(gè)方法
 ??中若有警告信息,則加以抑制,不用在編譯完成后出現(xiàn)警告。
 ??例:
 ??public class SomeClass2{
 ????@SuppressWarnings(value={"unchecked"});
 ????public void doSomething(){
 ??????Map map = new HashMap();
 ??????map.put("some","thing");
 ????}
 ??}
 ??這樣,編譯器將忽略unchecked的警告,您也可以指定忽略多個(gè)警告:
 ??@SuppressWarnings(value={"unchecked","deprecation"});
 ??@SuppressWarnings是所謂的Single-Value Annotation,因?yàn)檫@樣的Annotation只有一個(gè)成員,稱為
 ??value成員,可在使用Annotation時(shí)作額外的信息指定。
 ??
 ??
 ??
 自定義Annotation類型
 ??可以自定義Annotation類型,并使用這些自定義的Annotation類型在程序代碼中使用Annotation,這些
 ??Annotation將提供信息給程序代碼分析工具。
 ??首先來看看如何定義Marker Annotation,也就是Annotation名稱本身即提供信息。對于程序分析工具來
 ??說,主要是檢查是否有Marker Annotation的出現(xiàn),并做出對應(yīng)的動(dòng)作。要定義一個(gè)Annotation所需的動(dòng)作
 ??,就類似于定義一個(gè)接口,只不過使用的是@interface。
 ??例:
 ??public @interface Debug{}
 ??
 ??由于是一個(gè)Marker Annotation,所以沒有任何成員在Annotation定義中。編譯完成后,就可以在程序代碼
 ??中使用這個(gè)Annotation。
 ??public class SomeObject{
 ????@Debug
 ????public void doSomething(){
 ?????......
 ????}
 ??}
 ??稍后可以看到如何在Java程序中取得Annotation信息(因?yàn)橐褂肑ava程序取得信息,所以還要設(shè)置
 ??meta-annotation,稍后會(huì)談到)
 ??
 ??接著來看看如何定義一個(gè)Single-Value Annotation,它只有一個(gè)Value成員。
 ??例:
 ??public @interface UnitTest{
 ????String value();
 ??}
 ??實(shí)際上定義了value()方法,編譯器在編譯時(shí)會(huì)自動(dòng)產(chǎn)生一個(gè)value的域成員,接著在使用UnitTest 
 ??Annotation時(shí)要指定值。如:
 ??public class MathTool{
 ???@UnitTest("GCD")
 ???public static int gcdOf(int num1,int num2){
 ?????...............
 ???}
 ??}
 ??@UnitTest("GCD")實(shí)際上是@UnitTest(value="GCD")的簡便寫法,value也可以是數(shù)組值。如:
 ??public @interface FunctionTest{
 ????String[] value();
 ??}
 ??在使用時(shí),可以寫成@FunctionTest({"method1","method2"})這樣的簡便形式?;蚴?br /> ??@FunctionTest(value={"method1","method2"})這樣的詳細(xì)形式.
 ??
 ??也可以對value成員設(shè)置默認(rèn)值,使用default關(guān)鍵詞即可。
 ??例:
 ??public @interface UnitTest2{
 ????String value() default "noMethod";
 ??}
 ??這樣如果使用@UnitTest2時(shí)沒有指定value值,則value默認(rèn)就是noMethod.
 ??
 ??
 ??也可以為Annotation定義額外的成員,以提供額外的信息給分析工具,如:
 ??public @interface Process{
 ????public enum Current{NONE,REQUIRE,ANALYSIS,DESIGN,SYSTEM};
 ????Current current() default Current.NONE;
 ????String tester();
 ????boolean ok();
 ??}
 ??運(yùn)用:
 ??public class Application{
 ????@process(
 ??????current = Process.Current.ANALYSIS,
 ??????tester = "Justin Lin",
 ??????ok = true
 ????)
 ????public void doSomething(){
 ??????...........
 ????}
 ??}
 ??當(dāng)使用@interface自行定義Annotation類型時(shí),實(shí)際上是自動(dòng)繼承了
 ??java.lang.annotation接口,并由編譯器自動(dòng)完成其他產(chǎn)生的細(xì)節(jié),并且在定義Annotation類型時(shí),
 ??不能繼承其他的Annotation類型或接口.
 ??定義Annotation類型時(shí)也可以使用包機(jī)制來管理類。由于范例所設(shè)置的包都是onlyfun.caterpillar,
 ??所以可以直接使用Annotation類型名稱而不指定包名,但如果是在別的包下使用這些自定義的Annotation
 ??,記得使用import告訴編譯器類型的包們置。
 ??如:
 ??import onlyfun.caterpillar.Debug;
 ??public class Test{
 ????@Debug
 ????public void doTest(){
 ??????......
 ????}
 ??}
 ??或是使用完整的Annotation名稱.如:
 ??public class Test{
 ????@onlyfun.caterpillar.Debug
 ????public void doTest(){
 ??????......
 ????}
 ??}
 ??
 ??
 ??
 meta-annotation
 ??所謂neta-annotation就是Annotation類型的數(shù)據(jù),也就是Annotation類型的Annotation。在定義
 ??Annotation類型時(shí),為Annotation類型加上Annotation并不奇怪,這可以為處理Annotation類型
 ??的分析工具提供更多的信息。
 ??
 1??告知編譯器如何處理annotation @Retention
 ??java.lang.annotation.Retention類型可以在您定義Annotation類型時(shí),指示編譯器該如何對待自定
 ??義的Annotation類型,編譯器默認(rèn)會(huì)將Annotation信息留在.class文件中,但不被虛擬機(jī)讀取,而僅用
 ??于編譯器或工具程序運(yùn)行時(shí)提供信息。
 ??
 ??在使用Retention類型時(shí),需要提供java.lang.annotation.RetentionPolicy的枚舉類型。
 ??RetentionPolicy的定義如下所示:
 ??package java.lang.annotation;
 ??public enum RetentionPolicy{
 ????SOURCE,//編譯器處理完Annotation信息后就沒有事了
 ????CLASS,//編譯器將Annotation存儲于class文件中,默認(rèn)
 ????RUNTIME //編譯器將Annotation存儲于class文件中,可由VM讀入
??}
 ??
 ??RetentionPolicy為SOURCE的例子是@SuppressWarnings,這個(gè)信息的作用僅在編譯時(shí)期告知
 ??編譯器來抑制警告,所以不必將這個(gè)信息存儲在.class文件中。
 ??
 ??RetentionPolicy為RUNTIME的時(shí)機(jī),可以像是您使用Java設(shè)計(jì)一個(gè)程序代碼分析工具,您必須讓VM能讀出
 ??Annotation信息,以便在分析程序時(shí)使用,搭配反射機(jī)制,就可以達(dá)到這個(gè)目的。\
 ??
 ??J2SE6.0的java.lang.reflect.AnnotatedElement接口中定義有4個(gè)方法:
 ??public Annotation getAnnotation(Class annotationType)
 ??public Annotation[] getAnnotations();
 ??public Annotation[] getDeclaredAnnotations()
 ??public boolean isAnnotationPresent(Class annotationType);
 ??
 ??Class,Constructor,field,Method,Package等類,都實(shí)現(xiàn)了AnnotatedElement接口,所以可以從這些
 ??類的實(shí)例上,分別取得標(biāo)示于其上的Annotation與相關(guān)信息。由于在執(zhí)行時(shí)讀取Annotation信息,所以定
 ??義Annotation時(shí)必須設(shè)置RetentionPolicy為RUNTIME,也就是可以在VM中讀取Annotation信息。
 ??例:
 ??package onlyfun.caterpillar;
 ??import java.lang.annotation.Retention;
 ??import java.lang.annotation.RetentionPllicy;
 ??
 ??@Retention(RetentionPolicy.RUNTIME)
 ??public @interface SomeAnnotation{
 ????String value();
 ????String name();
 ??}
 ??由于RetentionPolicy為RUNTIME,編譯器在處理SomeAnnotation時(shí),會(huì)將Annotation及給定的相關(guān)信息
 ??編譯至.class文件中,并設(shè)置為VM可以讀出Annotation信息。接下來:
 ??package onlyfun.caterpillar;
 ??public class SomeClass3{
 ????@SomeAnotation{
 ??????value="annotation value1",
 ??????name="annotation name1"
 ????}
 ????public void doSomething(){
 ??????......
 ????}
 ??}
 ??
 ??
 ??現(xiàn)在假設(shè)要設(shè)計(jì)一個(gè)源代碼分析工具來分析所設(shè)計(jì)的類,一些分析時(shí)所需的信息已經(jīng)使用Annotation標(biāo)示于類
 ??中了,可以在執(zhí)行時(shí)讀取這些Annotation的相關(guān)信息。例:
 ??
 ??package onlyfun.caterpillar;
 ??
 ??import java.lang.annotation.Annotation;
 ??import java.lang.reflect.Method;
 ??
 ??public class AnalysisApp{
 ????public static void main(String [] args) throws NoSuchMethodException{
 ??????Class<SomeClass3> c = SomeClass3.class;
 ??????//因?yàn)镾omeAnnotation標(biāo)示于doSomething()方法上
 ??????//所以要取得doSomething()方法的Method實(shí)例
 ??????Method method = c.getMethod("doSomething");
 ??????//如果SomeAnnotation存在
 ??????if(method.isAnnotationPresent(SomeAnnotation.class){
 ????????System.out.println("找到@SomeAnnotation");
 ????????//取得SomeAnnotation
 ????????SomeAnnotation annotation = method.getAnnotation(SomeAnnotation.class);
 ????????//取得vlaue成員值
 ????????System.out.println(annotation.value);
 ????????//取得name成員值
 ????????System.out.println(annotation.name());
 ??????}else{
 ????????System.out.println("找不到@SomeAnnotation");
 ??????}
 ??????//取得doSomething()方法上所有的Annotation
 ??????Annotation[] annotations = method.getAnnotations();
 ??????//顯示Annotation名稱
 ??????for(Annotation annotation : annotations){
 ????????System.out.println("Annotation名稱:"+annotation.annotationType().getName());
 ??????}
 ????}
 ??}
 ??若Annotation標(biāo)示于方法上,就要取得方法的Method代表實(shí)例,同樣的,如果Annotation標(biāo)示于類或包上,
 ??就要分別取得類的Class代表的實(shí)例或是包的Package代表的實(shí)例。之后可以使用實(shí)例上的getAnnotation()
 ??等相關(guān)方法,以測試是否可取得Annotation或進(jìn)行其他操作。
 ??
 2??限定annotation使用對象 @Target
 ??在定義Annotation類型時(shí),使用java.lang.annotation.Target可以定義其適用的時(shí)機(jī),在定義時(shí)要指定
 ??java.lang.annotation.ElementType的枚舉值之一。
 ??public enum elementType{
 ????TYPE,//適用class,interface,enum
 ????FIELD,//適用于field
 ????METHOD,//適用于method
 ????PARAMETER,//適用method上之parameter
 ????CONSTRUCTOR,//適用constructor
 ????LOCAL_VARIABLE,//適用于區(qū)域變量
 ????ANNOTATION_TYPE,//適用于annotation類型
 ????PACKAGE,//適用于package
 ??}
 ??
 ??舉例,假設(shè)定義Annotation類型時(shí),要限定它只能適用于構(gòu)造函數(shù)與方法成員,則:
 ??package onlyfun.caterpillar;
 ??
 ??import java.lang.annotation.Target;
 ??import java.lang.annotation.ElementType;
 ??
 ??@Target({ElementType.CONSTRUCTOR,ElementType.METHOD})
 ??public @interface MethodAnnotation{}
 ??
 ??將MethodAnnotation標(biāo)示于方法之上,如:
 ??
 ??public class SomeoneClass{
 ????@onlyfun.caterpillar.MethodAnnotation
 ????public void doSomething(){
 ??????......
 ????}
 ??}
 ??
 3??要求為API文件的一部分 @Documented
 ?
 ??在制作Java Doc文件時(shí),并不會(huì)默認(rèn)將Annotation的數(shù)據(jù)加入到文件中.Annnotation用于標(biāo)示程序代碼以便
 ??分析工具使用相關(guān)信息,有時(shí)Annotation包括了重要的信息,您也許會(huì)想要在用戶制作Java Doc文件的同時(shí),
 ??也一并將Annotation的信息加入到API文件中。所以在定義Annotation類型時(shí),可以使用
 ??java.lang.annotation.Documented.例:
 ??
 ??package onlyfun.caterpillar;
 ??
 ??import java.lang.annotation.Documented;
 ??import java.lang.annotation.Retention;
 ??import java.lang.annotation.RetentionPolicy;
 ??
 ??@Documented
 ??@Retention(RetentionPolicy.RUNTIME)
 ??public @interface TwoAnnotation{}
 ??
 ??使用java.lang.annotation.Documented為定義的Annotation類型加上Annotation時(shí),必須同時(shí)使用Retention
 ??來指定編譯器將信息加入.class文件,并可以由VM讀取,也就是要設(shè)置RetentionPolicy為RUNTIME。接著可以使
 ??用這個(gè)Annotation,并產(chǎn)生Java Doc文件,這樣可以看到文件中包括了@TwoAnnotation的信息.
 ??
 4??子類是否可以繼承父類的annotation @Inherited
 ??在定義Annotation類型并使用于程序代碼上后,默認(rèn)父類中的Annotation并不會(huì)被繼承到子類中。可以在定義
 ??Annotation類型時(shí)加上java.lang.annotation.Inherited類型的Annotation,這讓您定義的Annotation類型在
 ??被繼承后仍可以保留至子類中。
 ??例:
 ??package onlyfun.caterpillar;
 ??
 ??import java.lang.annotation.Retention;
 ??import java.lang.annotation.RetentionPolicy;
 ??import java.lang.annotation.Inherited;
 ??
 ??@Retention(RetentionPolicy.RUNTIME)
 ??@Inherited
 ??public @interface ThreeAnnotation{
 ????String value();
 ????String name();
 ??}
 ??可以在下面的程序中使用@ThreeAnnotation:
 ??public class SomeoneClass{
 ????@onlyfun.caterpillar.ThreeAnnotation(
 ??????value = "unit",
 ??????name = "debug1"
 ????)
 ????public void doSomething(){
 ??????.....
 ????}
 ??}
 ??如果有一個(gè)類繼承了SomeoneClass類,則@ThreeAnnotation也會(huì)被繼承下來。
?
總結(jié)
以上是生活随笔為你收集整理的Java Annotation详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: linux 使用 touch 修改文件的
- 下一篇: 同步锁ReentrantLock
