Java注解之Repeatable解讀
Java注解之Repeatable
Repeatable使用場景
在需要對同一種注解多次使用時,往往需要借助@Repeatable。
實(shí)例
在生活中一個人往往是具有多種身份,如果我把每種身份當(dāng)成一種注解該如何使用???
先聲明一個Persons類用來包含所有的身份
@Target(ElementType.TYPE) ?
@Retention(RetentionPolicy.RUNTIME)
public ? @interface Persons {
?? ?Person[] value();
}這里@Target是聲明Persons注解的作用范圍,參數(shù)ElementType.Type代表可以給一個類型進(jìn)行注解,比如類,接口,枚舉,注解。
@Retention是注解的有效時間,RetentionPolicy.RUNTIME是指程序運(yùn)行的時候。
Person注解:
@Repeatable(Persons.class)
public ?@interface Person{
?? ?String role() default "";
}@Repeatable括號內(nèi)的就相當(dāng)于用來保存該注解內(nèi)容的容器。
聲明一個Man類,給該類加上一些身份。
@Person(role="CEO")
@Person(role="husband")
@Person(role="father")
@Person(role="son")
public ? class Man {
?? ?String name="";
}在主方法中訪問該注解。
? ? public static void main(String[] args) {
? ? ? ? Annotation[] annotations = Man.class.getAnnotations(); ?
? ? ? ? System.out.println(annotations.length);
? ? ? ? Persons p1=(Persons) annotations[0];
? ? ? ? for(Person t:p1.value()){
? ? ? ? ?? ?System.out.println(t.role());
? ? ? ? }
? ? }下面的代碼結(jié)果輸出相同,但是可以先判斷是否是相應(yīng)的注解,比較嚴(yán)謹(jǐn)。
if(Man.class.isAnnotationPresent(Persons.class)) {
? ? Persons p2=Man.class.getAnnotation(Persons.class);
? ? for(Person t:p2.value()){
? ? ? ? System.out.println(t.role());
? ? }
?}運(yùn)行結(jié)果:
1
CEO
husband
father
son
對@Repeatable的理解
@Repeatable是jdk8中新增的注解,使用如Spring中的@ComponentScan注解。
在沒有@Repeatable注解的的注解中,在同一個地方使用相同的注解會報錯,有了此元注解注解的注解,就可以在同一個地方使用相同的注解。
其官方文檔如下:
The annotation type {@code java.lang.annotation.Repeatable} is used to indicate that the annotation type whose declaration it (meta-)annotates is repeatable.
The value of @Repeatable indicates the containing annotation type for the repeatable annotation type.
@Repeatable 注解是用于聲明其它類型注解的元注解,來表示這個聲明的注解是可重復(fù)的。
@Repeatable的值是另一個注解,其可以通過這個另一個注解的值來包含這個可重復(fù)的注解。
示例
Value注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Values.class)
public @interface Value {
String value() default "value";
}Values注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Values {
Value[] value();
}其中,@Value注解上的元注解@Repeatable中的值,使用了@Values注解,@Values注解中包含的值類型是一個@Value注解的數(shù)組!
這就解釋了官方文檔中@Repeatable中值的使用。
測試
注解使用方法
public class AnnotationClass {
@Value("hello")
@Value("world")
public void test(String var1, String var2) {
System.out.println(var1 + " " + var2);
}
}測試用例
// 獲取使用`@Value`注解的`test`方法,并打印這個方法上的注解長度和信息
@Test
public void testValue() {
Method[] methods = AnnotationClass.class.getMethods();
for (Method method : methods){
if (method.getName().equals("test")) {
Annotation[] annotations = method.getDeclaredAnnotations();
System.out.println(annotations.length);
System.out.println(method.getName() + " = " + Arrays.toString(annotations));
}
}
}因?yàn)?code>test方法上使用了兩個@Value注解,所以猜測打印注解長度為2,然后打印詳情,可是結(jié)果并不同。
1
test = [@com.example.annotations.Values(value=[@com.example.annotations.Value(value=hello), @com.example.annotations.Value(value=world)])]
結(jié)果顯示,test方法上的注解長度為 1 , 且打印信息為@Values注解,它的值包含了使用的兩個注解。
因此可知在jdk8中,相同注解只是以集合的方式進(jìn)行了保存,原理并沒有變化。
注意事項(xiàng)
一些約束
@Repeatable 所聲明的注解,其元注解@Target的使用范圍要比@Repeatable的值聲明的注解中的@Target的范圍要大或相同,否則編譯器錯誤,顯示@Repeatable值所聲明的注解的元注解@Target不是@Repeatable聲明的注解的@Target的子集
// Value
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Values.class)
public @interface Value {
String value() default "value";
}
// Values
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Values {
Value[] value();
}錯誤提示信息:

@Repeatable注解聲明的注解的元注解@Retention的周期要比@Repeatable的值指向的注解的@Retention得周期要小或相同。
周期長度為 SOURCE(源碼) < CLASS (字節(jié)碼) < RUNTIME(運(yùn)行)
// Value 注意 @Retention的值
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Values.class)
public @interface Value {
String value() default "value";
}
// Values
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.CLASS)
public @interface Values {
Value[] value();
}
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring boot整合log4j2及MQ消費(fèi)處理系統(tǒng)日志示例
這篇文章主要為大家介紹了spring boot整合log4j2及MQ消費(fèi)處理系統(tǒng)日志的示例過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
詳解Http請求中Content-Type講解以及在Spring MVC中的應(yīng)用
這篇文章主要介紹了Http請求中Content-Type講解以及在Spring MVC中的應(yīng)用的相關(guān)資料,需要的朋友可以參考下2017-02-02
在@Value注解內(nèi)使用SPEL自定義函數(shù)方式
這篇文章主要介紹了在@Value注解內(nèi)使用SPEL自定義函數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
springboot+redis實(shí)現(xiàn)訂單過期(超時取消)功能的方法詳解
在Spring Boot中使用Redis實(shí)現(xiàn)訂單過期(超時取消)功能,有多種成熟方案,本文為大家整理了幾個詳細(xì)方法,文中的示例代碼講解詳細(xì),大家可以根據(jù)需要進(jìn)行選擇2025-12-12
nacos配置中心遠(yuǎn)程調(diào)用讀取不到配置文件的解決
這篇文章主要介紹了nacos配置中心遠(yuǎn)程調(diào)用讀取不到配置文件的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。2022-01-01
MyBatis中的表關(guān)聯(lián)查詢實(shí)現(xiàn)示例
這篇文章主要介紹了MyBatis中的表關(guān)聯(lián)查詢實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Java實(shí)戰(zhàn)之實(shí)現(xiàn)文件資料上傳并生成縮略圖
這篇文章主要介紹了通過Java實(shí)現(xiàn)文件資料的上傳并生成一個縮略圖,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定的幫助,感興趣的小伙伴可以了解一下2021-12-12
WebUploader客戶端批量上傳圖片 后臺使用springMVC
這篇文章主要為大家詳細(xì)介紹了WebUploader客戶端批量上傳圖片,后臺使用springMVC接收實(shí)例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09
Java多線程應(yīng)用循環(huán)輸出ABC方式
這篇文章主要介紹了Java多線程應(yīng)用循環(huán)輸出ABC方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-05-05

