一、什么是注釋
說(shuō)起注釋,得先提一提什么是元數(shù)據(jù)(metadata)。所謂元數(shù)據(jù)就是數(shù)據(jù)的數(shù)據(jù)。也就是說(shuō),元數(shù)據(jù)是描述數(shù)據(jù)的。就象數(shù)據(jù)表中的字段一樣,每個(gè)字段描 述了這個(gè)字段下的數(shù)據(jù)的含義。而J2SE5.0中提供的注釋就是java源代碼的元數(shù)據(jù),也就是說(shuō)注釋是描述java源代碼的。在J2SE5.0中可以自 定義注釋。使用時(shí)在@后面跟注釋的名字。
二、J2SE5.0中預(yù)定義的注釋
在J2SE5.0的java.lang包中預(yù)定義了三個(gè)注釋。它們是Override、Deprecated和SuppressWarnings。下面分別解釋它們的含義。
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注釋:?jiǎn)我蛔⑨專梢酝ㄟ^(guò)數(shù)組提供變量,變量值指明要阻止的特定類(lèi)型警告(忽略某些警告)。數(shù)組中的變量指明要阻 止的警告@SuppressWarnings(value={”unchecked”,”fallthrough”}))
三、自定義注釋@interface
@interface:注釋聲明,定義注釋類(lèi)型(與默認(rèn)的Override等三種注釋類(lèi)型類(lèi)似)。請(qǐng)看下面實(shí)例:
注釋類(lèi)1:
package a.test;
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.TYPE)
public @interface FirstAnno {
String value() default "FirstAnno";
}
注釋類(lèi)2:
package a.test;
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 SecondAnnotation {
// 注釋中含有兩個(gè)參數(shù)
String name() default "Hrmzone";
String url() default "hrmzone.cn";
}
注釋類(lèi)3:
package a.test;
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.FIELD)
public @interface Kitto {
String value() default "kitto";
}
使用類(lèi):
package a.test;
@FirstAnno("http://hrmzone.cn")
public class Anno {
@Kitto("測(cè)試")
private String test = "";
// 不賦值注釋中的參數(shù),使用默認(rèn)參數(shù)
@SecondAnnotation()
public String getDefault() {
return "get default Annotation";
}
@SecondAnnotation(name="desktophrm",url="desktophrm.com")
public String getDefine() {
return "get define Annotation";
}
}
測(cè)試類(lèi):
package a.test;
import java.lang.reflect.Field;
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("a.test.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++) {
list.add(method[i]);
}
for (Method m : list) {
SecondAnnotation anno = m.getAnnotation(SecondAnnotation.class);
if(anno == null)
continue;
System.out.println("second annotation's\nname:\t" + anno.name()
+ "\nurl:\t" + anno.url());
}
List<Field> fieldList = new ArrayList<Field>();
for(Field f : c.getDeclaredFields()){//訪問(wèn)所有字段
Kitto k = f.getAnnotation(Kitto.class);
System.out.println("----kitto anno: " + k.value());
}
}
}
結(jié)合源文件中注釋,想必對(duì)注釋的應(yīng)用有所了解。下面深入了解。
深入注釋:
@Target:指定程序元定義的注釋所使用的地方,它使用了另一個(gè)類(lèi):ElementType,是一個(gè)枚舉類(lèi)定義了注釋類(lèi)型可以應(yīng)用到不同的程序元素以免使用者誤用。看看java.lang.annotation 下的源代碼:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
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è)成員變量,可以不用指明成名名稱而賦值,看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;(所有的都能訪問(wèn),源作者沒(méi)用到函數(shù):getDeclaredFields而已)
3.成員變量的只能使用基本類(lèi)型(byte、short、int、char、long、double、float、boolean和String、Enum、Class、annotations以及該類(lèi)型的數(shù)據(jù))(沒(méi)有限制,大家可以修改測(cè)試一下,就清楚)
4.如果只有一個(gè)成員變量,最好將參數(shù)名稱設(shè)為value,賦值時(shí)不用制定名稱而直接賦值
5.在實(shí)際應(yīng)用中,還可以使用注釋讀取和設(shè)置Bean中的變量。