Java注释(Annotation)详解
注釋:在一個(gè)類(lèi)中可以有多個(gè),類(lèi)似于一個(gè)類(lèi)可以有多個(gè)實(shí)例;
?????注釋類(lèi)型:是注釋使用的結(jié)構(gòu),類(lèi)似于類(lèi),僅有一個(gè)版本,因此多個(gè)注釋可能使用相同的注釋類(lèi)型
?????jdk默認(rèn)的三個(gè)注釋:
???????1.Override注釋:僅用于方法(不可用于類(lèi)、包的生命或其他),指明注釋的方法將覆蓋超類(lèi)中的方法(如果覆蓋父類(lèi)的方法而沒(méi)有注
釋就無(wú)法編譯該類(lèi)),注釋還能確保注釋父類(lèi)方法的拼寫(xiě)是正確(錯(cuò)誤的編寫(xiě),編譯器不認(rèn)為是子類(lèi)的新方法,而會(huì)報(bào)錯(cuò))
???????2.@Deprecated注釋:對(duì)不應(yīng)再使用的方法進(jìn)行注釋,與正在聲明為過(guò)時(shí)的方法放在同一行。使用被?????Deprecated注釋的方法,編譯器會(huì)
提示方法過(guò)時(shí)警告(”Warring”)
???????3.@SuppressWarnings注釋:單一注釋,可以通過(guò)數(shù)組提供變量,變量值指明要阻止的特定類(lèi)型警告(忽略某些警告)。數(shù)組中的變量指明要阻止的警告@SuppressWarnings(value={“unchecked”,”fallthrough”}))
?????上面提到“單一注釋”這個(gè)概念,他表示注釋的類(lèi)型,java中有三種類(lèi)型的注釋:
???????1.標(biāo)記注釋:由名稱(chēng)標(biāo)記,未提供數(shù)據(jù),@MarkerAnnotation
???????2.單一注釋:與標(biāo)記注釋類(lèi)似,但提供了一段很少一點(diǎn)的數(shù)據(jù),很類(lèi)似普通的java方法調(diào)用(@SingleValueAnnotation(“my data”)
???????3.完整注釋:有多個(gè)數(shù)據(jù)成員,必須提供完整的語(yǔ)法(@FullAnnotation(var=”data value”,var2=”data value2″,var3=”data value3″))除了通過(guò)默認(rèn)語(yǔ)法向注釋提供值,還可以通過(guò)花括號(hào)為注釋變量提供值數(shù)組,數(shù)組用”,”分割
自定義注釋:
?????@interface:注釋聲明,定義注釋類(lèi)型(與默認(rèn)的Override等三種注釋類(lèi)型類(lèi)似),使用時(shí)與內(nèi)置注釋類(lèi)型類(lèi)似。使用定制注釋類(lèi)型時(shí),要將注釋定義類(lèi)導(dǎo)入,或者直接引入包名。(定義注釋類(lèi)型和定義類(lèi)非常類(lèi)似,僅在注釋類(lèi)型名稱(chēng)前多了@interface),自定義注釋類(lèi)型中的變量如同類(lèi)中的方法定義需要”()”,并以”;”結(jié)束
?????在使用有變量的注釋類(lèi)型時(shí),需要制定數(shù)據(jù)類(lèi)型的名稱(chēng),但是如果注釋類(lèi)型中只有一個(gè)變量,最好將參數(shù)名稱(chēng)設(shè)為value,賦值時(shí)不用指定定名稱(chēng)而直接賦值如:變量名稱(chēng)(@AnnotationType(var value)),否則需要制定變量的名稱(chēng)(@Annotation(varname=varvalue))
?????注釋類(lèi)型的默認(rèn)值:在定義注釋的成員變量,需要在成員的聲明后添加關(guān)鍵字(default)并對(duì)其賦值(默認(rèn)值),注意默認(rèn)值的類(lèi)型必須和成員變量的類(lèi)型一致。在使用該注釋類(lèi)型時(shí),如果沒(méi)有給該注釋類(lèi)型的成員變量賦值即用默認(rèn)值
?????現(xiàn)在自定義注釋來(lái)演示:
?????1.在eclipse中新建一個(gè)Annotation類(lèi):FirstAnno.java
?????2.再新建一個(gè)Annotation類(lèi):SecondAnnotation:
package cn.hrmzone.anno;import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SecondAnno { // 注釋中含有兩個(gè)參數(shù)String name() default "Hrmzone";String url() default "hrmzone.cn"; } ?????這個(gè)時(shí)候,估計(jì)對(duì)
?????@Documented
?????@Retention(RetentionPolicy.RUNTIME)
?????@Target(ElementType.METHOD)
?????這三個(gè)注釋有很多疑問(wèn)了吧,先將演示完成在解釋:
?????3.新建一個(gè)使用以上定義的兩個(gè)注釋的類(lèi):Anno.java
?????4.測(cè)試注釋:AnnoTest.class
package cn.hrmzone.anno;import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List;public class AnnoTest {public static void main(String[] args) throws ClassNotFoundException { // 要使用到反射中的相關(guān)內(nèi)容Class c=Class.forName("cn.hrmzone.anno.Anno");Method[] method=c.getMethods();boolean flag=c.isAnnotationPresent(FirstAnno.class);if(flag) {FirstAnno first=(FirstAnno) c.getAnnotation(FirstAnno.class);System.out.println("First Annotation:"+first.value()+"\n");}List<Method> list=new ArrayList<Method>();for(int i=0;i<method.length;i++) {boolean f=method[i].isAnnotationPresent(SecondAnno.class);if(f) {list.add(method[i]);} }for(Method m:list) {SecondAnno anno=m.getAnnotation(SecondAnno.class);System.out.println("second annotation's\nname:\t"+anno.name()+"\nurl:\t"+anno.url());}} }?????測(cè)試的輸出結(jié)果為:
First Annotation:http://hrmzone.cnsecond annotation's name: desktophrm url: desktophrm.com second annotation's name: Hrmzone url: hrmzone.cn ?????結(jié)合源文件中注釋,想必對(duì)注釋的應(yīng)用有所了解。下面深入了解。
?????深入注釋:
?????上面的兩個(gè)Annotation類(lèi)中有三個(gè)奇怪的注釋,他們是元注釋。
?????元注釋:注釋的注釋,對(duì)注釋進(jìn)行注釋,下面分別介紹這三個(gè)注釋:
?????@Target:指定程序元定義的注釋所使用的地方,它使用了另一個(gè)類(lèi):ElementType,是一個(gè)枚舉類(lèi)定義了注釋類(lèi)型可以應(yīng)用到不同的程序元素以免使用者誤用。看看java.lang.annotation 下的源代碼:
?????ElementType是一個(gè)枚舉類(lèi)型,指明注釋可以使用的地方,看看ElementType類(lèi):
public enum ElementType { TYPE, // 指定適用點(diǎn)為 class, interface, enum FIELD, // 指定適用點(diǎn)為 field METHOD, // 指定適用點(diǎn)為 method PARAMETER, // 指定適用點(diǎn)為 method 的 parameter CONSTRUCTOR, // 指定適用點(diǎn)為 constructor LOCAL_VARIABLE, // 指定使用點(diǎn)為 局部變量 ANNOTATION_TYPE, //指定適用點(diǎn)為 annotation 類(lèi)型 PACKAGE // 指定適用點(diǎn)為 package }?????@Retention:這個(gè)元注釋和java編譯器處理注釋的注釋類(lèi)型方式相關(guān),告訴編譯器在處理自定義注釋類(lèi)型的幾種不同的選擇,需要使用RetentionPolicy枚舉類(lèi)。此枚舉類(lèi)只有一個(gè)成員變量,可以不用指明成名名稱(chēng)而賦值,看Retention的源代碼:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { RetentionPolicy value(); }?????類(lèi)中有個(gè)RetentionPolicy類(lèi),也是一個(gè)枚舉類(lèi),具體看代碼:
public enum RetentionPolicy { SOURCE, // 編譯器處理完Annotation后不存儲(chǔ)在class中 CLASS, // 編譯器把Annotation存儲(chǔ)在class中,這是默認(rèn)值 RUNTIME // 編譯器把Annotation存儲(chǔ)在class中,可以由虛擬機(jī)讀取,反射需要 } ?????@Documented:是一個(gè)標(biāo)記注釋,表示注釋?xiě)?yīng)該出現(xiàn)在類(lèi)的javadoc中,因?yàn)樵谀J(rèn)情況下注釋時(shí)不包括在javadoc中的。所以如果花費(fèi)了大量的時(shí)間定義一個(gè)注釋類(lèi)型,并想描述注釋類(lèi)型的作用,可以使用它。注意他與@Retention(RetentionPolicy.RUNTIME)配合使用,因?yàn)橹挥袑⒆⑨尡A粼诰幾g后的類(lèi)文件中由虛擬機(jī)加載,然后javadoc才能將其抽取出來(lái)添加至javadoc中。
?????@Inherited:將注釋同樣繼承至使用了該注釋類(lèi)型的方法中(表達(dá)有點(diǎn)問(wèn)題,就是如果一個(gè)方法使用了的注釋用了@inherited,那么其子類(lèi)的該方法同樣繼承了該注釋)
注意事項(xiàng):
?????1.所有的Annotation自動(dòng)繼承java.lang.annotation接口
?????2.自定義注釋的成員變量訪問(wèn)類(lèi)型只能是public、default;
?????3.成員變量的只能使用基本類(lèi)型(byte、short、int、char、long、double、float、boolean和String、Enum、Class、annotations以及該類(lèi)型的數(shù)據(jù))
?????4.如果只有一個(gè)成員變量,最好將參數(shù)名稱(chēng)設(shè)為value,賦值時(shí)不用制定名稱(chēng)而直接賦值
?????5.在實(shí)際應(yīng)用中,還可以使用注釋讀取和設(shè)置Bean中的變量。
總結(jié)
以上是生活随笔為你收集整理的Java注释(Annotation)详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 自己动手写Tomcat
- 下一篇: java美元兑换,(Java实现) 美元