Java注解又稱Java標(biāo)注国葬,是Java語(yǔ)言5.0版本開(kāi)始支持加入源代碼的特殊語(yǔ)法元數(shù)據(jù)
Java語(yǔ)言中的類安吁、方法趋翻、變量睛琳、參數(shù)和包等都可以被標(biāo)注。和Javadoc不同踏烙,Java標(biāo)注可以通過(guò)反射獲取標(biāo)注內(nèi)容师骗。在編譯器生成類文件時(shí),標(biāo)注可以被嵌入到字節(jié)碼中讨惩。Java虛擬機(jī)可以保留標(biāo)注內(nèi)容辟癌,在運(yùn)行時(shí)可以獲取到標(biāo)注內(nèi)容。 當(dāng)然它也支持自定義Java標(biāo)注.
元注解
Java中共有四種元注解:
//表示帶有該注解的元素能被文檔化
@Documented
//表示可被該注解修飾的元素種類
@Target
//表示該注解的作用域
@Retention
//表示該注解被自動(dòng)繼承
@Inherited
Documented
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}```
@Documented表示被該注解修飾的元素能被Javadoc等工具文檔化荐捻,但是注意到被@Target注解修飾且Target只能是Annotation類型黍少,說(shuō)明該注解只能用來(lái)修飾注解。作用域可至運(yùn)行時(shí)处面。
@interface 定義注解的關(guān)鍵字厂置。
#### Target
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}```
注意到Target和Documented注解有所不同,Target注解有方法體魂角,返回值是一個(gè)ElementType類型的數(shù)組昵济,ElementType是一個(gè)枚舉類型,有TYPE(類、接口访忿、枚舉)瞧栗,METHOD(方法),F(xiàn)IELD(字段)海铆,PARAMETER(參數(shù))迹恐,CONSTRUCTOR(構(gòu)造函數(shù)),LOCAL_VARIABLE(局部變量)卧斟,ANNOTATION_TYPE(注解類型)殴边,PACKAGE(包),TYPE_PARAMETER(類型參數(shù)唆涝,1.8)找都,TYPE_USE(類型使用,1.8)廊酣,分別代表可被修飾的元素類型 能耻。Target可傳入一個(gè)或多個(gè)屬性。
@Target(ElementType.ANNOTATION_TYPE)表示Target注解只能用來(lái)修飾注解亡驰,同時(shí)作用域?yàn)檫\(yùn)行時(shí)晓猛。
@Retention
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}```
方法體中RetentionPolicy同樣是一個(gè)枚舉類型,SOURCE(保留在源文件凡辱,編譯時(shí)被丟棄)戒职,CLASS(保留在源文件、編譯后的class字節(jié)碼透乾,在運(yùn)行時(shí)被丟棄)洪燥,RUNTIME(一直保留直到運(yùn)行時(shí))。保留在運(yùn)行時(shí)的可以通過(guò)反射去獲得乳乌。
Retention也只能用來(lái)修飾注解捧韵,且作用域到運(yùn)行時(shí)。
#### Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}```
Inherited表示注解是被自動(dòng)繼承的汉操,即如果要在當(dāng)前類查找這個(gè)元注解類型再来,但當(dāng)前類并沒(méi)有聲明,將自動(dòng)去其父類去尋找磷瘤,直到找到或者找到頂層父類為止芒篷。注意這個(gè)被這個(gè)元注解標(biāo)注的注解作用在類級(jí)別上,子類可以繼承父類的注解采缚,反之不可以针炉。
Java中常用注解
@Override
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}```
告訴編輯器要復(fù)寫超類的方法。@Override只能用于修飾方法仰担,且作用域只停留在源碼級(jí)別糊识,即編譯時(shí)會(huì)被丟棄绩社,起標(biāo)記作用摔蓝。
#### @SuppressWarnings
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}```
用于告訴編輯器忽略警告信息赂苗。可用于修飾類贮尉、接口拌滋、字段、方法猜谚、參數(shù)败砂、構(gòu)造函數(shù)、局部變量魏铅。作用域停留在源碼級(jí)別昌犹。
@SuppressWarnings使用時(shí)需要一個(gè)String類型的數(shù)組,如uncheck(忽略泛型未轉(zhuǎn)換的警告)览芳,deprecation(忽略使用了過(guò)時(shí)的方法或字段警告)等斜姥。
@Deprecated
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}```
用來(lái)告訴編輯器,此方法沧竟、字段等不贊成使用铸敏。作用域?yàn)檫\(yùn)行時(shí)。
# 反射獲得運(yùn)行時(shí)注解
注解由@Retention(RetentionPolicy.RUNTIME)修飾的為運(yùn)行時(shí)注解悟泵,我們可以通過(guò)運(yùn)行時(shí)反射獲得注解信息杈笔。
比如我們自定義一個(gè)注解:
@Inherited
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
String value() default "Boss";
}```
定義注解要用@interface關(guān)鍵字,target為方法糕非,作用域?yàn)檫\(yùn)行時(shí)蒙具,需要傳入一個(gè)String類型的參數(shù),注意到default “Boss”朽肥,即如果沒(méi)有傳參數(shù)將返回“Boss”禁筏,這個(gè)注解的意義為可以在方法體上使用該注解用于告知該函數(shù)的作者。
我們可以這樣用:
@Author("Jack")
public void autorTest(){
System.out.print("I am author");
}```
如何通過(guò)反射在運(yùn)行時(shí)獲得Author信息呢鞠呈?
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
String className = "AnnotationTest";
Method[] methods = Main.class.getClassLoader().loadClass(className).getMethods();
for (Method method : methods) {
//判斷該元素是否存在指定注解
if (method.isAnnotationPresent(Author.class)) {
//獲得該元素指定注解
Author author = method.getAnnotation(Author.class);
System.out.println("Author is " + author.value());
}
}
}
}```
首先通過(guò)反射獲得制定類中的所有方法融师,遍歷所有方法,找出其中含有制定注解的方法蚁吝,在通過(guò)getAnnotation方法獲得指定注解旱爆,進(jìn)而可以獲得注解信息。
需要用到的幾個(gè)方法:
//判斷是否被指定注解標(biāo)注
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
//返回該元素所有注解
public Annotation[] getAnnotations()
//返回該元素指定注解
public <T extends Annotation> T getAnnotation(Class<T> annotationClass)```
這樣我們就完成了通過(guò)反射獲得運(yùn)行時(shí)注解窘茁。