欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java的@Repeatable注解使用詳細(xì)解析

 更新時(shí)間:2024年02月02日 08:32:51   作者:小徐也要努力鴨  
這篇文章主要介紹了Java的@Repeatable注解使用詳細(xì)解析,java8新增了注解@Repeatable,在hibernate-validator的源碼注解如@MAX、@NotNull等中,有@Repeatable注解的使用,需要的朋友可以參考下

1 前言

java8新增了注解@Repeatable,在hibernate-validator的源碼注解如@MAX、@NotNull等中,有@Repeatable注解的使用,源碼示例如下:

/*
 * Jakarta Bean Validation API
 *
 * License: Apache License, Version 2.0
 * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
 */
package javax.validation.constraints;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.constraints.NotNull.List;
/**
 * The annotated element must not be {@code null}.
 * Accepts any type.
 *
 * @author Emmanuel Bernard
 */
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(List.class)
@Documented
@Constraint(validatedBy = { })
public @interface NotNull {
	String message() default "{javax.validation.constraints.NotNull.message}";
	Class<?>[] groups() default { };
	Class<? extends Payload>[] payload() default { };
	/**
	 * Defines several {@link NotNull} annotations on the same element.
	 *
	 * @see javax.validation.constraints.NotNull
	 */
	@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
	@Retention(RUNTIME)
	@Documented
	@interface List {
		NotNull[] value();
	}
}

2 使用

參考hibernate-validator注解,使用@Repeatable:

2.1 新建注解RepeaDemo

暫時(shí)不添加@Repeatable:

package com.xiaoxu.tool.demo;

import java.lang.annotation.*;

@Target(value = {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeaDemo {
    String id();
    String name();
}

新建demo類(lèi):

package com.xiaoxu.tool.demo;
import java.lang.reflect.Field;
import java.util.Arrays;
/**
 * @author xiaoxu
 * @date 2022-05-17
 * spring_boot:com.xiaoxu.tool.demo.TestRepeatable
 */
public class TestRepeatable {
    @RepeaDemo(id = "1001",name = "荔枝")
    private String fruit1;
    @RepeaDemo(id = "1002",name = "葡萄")
    private String fruit2;
    public static void demo1(){
        Class<?> a = TestRepeatable.class;
        Field[] fruits = a.getDeclaredFields();
        Arrays.stream(fruits).forEach(f->{
            if(f.isAnnotationPresent(RepeaDemo.class)){
                RepeaDemo anno = f.getAnnotation(RepeaDemo.class);
                String id = anno.id();
                String name = anno.name();
                System.out.printf("水果id:%s,水果名稱:%s%n",id,name);
            }
        });
    }
    public static void main(String[] args) {
        demo1();
    }
}

執(zhí)行結(jié)果如下:

水果id:1001,水果名稱:荔枝
水果id:1002,水果名稱:葡萄

但是問(wèn)題是,如果希望在字段上增加多個(gè)注解,那么會(huì)提示Duplicate annotation.錯(cuò)誤:

在這里插入圖片描述

于是考慮新增一個(gè)RepeaDemos注解,用于存儲(chǔ)@RepeaDemo注解數(shù)組,就可以達(dá)到多個(gè)注解的使用了,如下:

package com.xiaoxu.tool.demo;

import java.lang.annotation.*;

@Target(value = {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeaDemos {
    RepeaDemo[] repeaDemos();
}

修改TestRepeatable代碼:

package com.xiaoxu.tool.demo;

import java.lang.reflect.Field;
import java.util.Arrays;

/**
 * @author xiaoxu
 * @date 2022-05-17
 * spring_boot:com.xiaoxu.tool.demo.TestRepeatable
 */
public class TestRepeatable {
    @RepeaDemos(repeaDemos = {
        @RepeaDemo(id = "1001",name = "荔枝"),
        @RepeaDemo(id = "1003",name = "沃柑")
    })
    private String fruit1;

    @RepeaDemo(id = "1002",name = "葡萄")
    private String fruit2;

    public static void demo1(){
        Class<?> a = TestRepeatable.class;
        Field[] fruits = a.getDeclaredFields();
        Arrays.stream(fruits).forEach(f->{
            if(f.isAnnotationPresent(RepeaDemo.class)){
                RepeaDemo anno = f.getAnnotation(RepeaDemo.class);
                String id = anno.id();
                String name = anno.name();
                System.out.printf("水果id:%s,水果名稱:%s%n",id,name);
            }
        });
    }

    public static void demo2(){
        Class<?> a = TestRepeatable.class;
        Field[] fruits = a.getDeclaredFields();
        Arrays.stream(fruits).forEach(f->{
            if(f.isAnnotationPresent(RepeaDemos.class)){
                RepeaDemos anno = f.getAnnotation(RepeaDemos.class);
                RepeaDemo[] res= anno.repeaDemos();
                Arrays.stream(res).forEach(r-> System.out.printf("水果id:%s,水果名稱:%s%n",r.id(),r.name()));
            }
            if(f.isAnnotationPresent(RepeaDemo.class)){
                RepeaDemo anno = f.getAnnotation(RepeaDemo.class);
                String id = anno.id();
                String name = anno.name();
                System.out.printf("水果id:%s,水果名稱:%s%n",id,name);
            }
        });
    }
    public static void main(String[] args) {
        demo2();
    }
}

執(zhí)行結(jié)果如下:

水果id:1001,水果名稱:荔枝
水果id:1003,水果名稱:沃柑
水果id:1002,水果名稱:葡萄

2.2 @Repeatable注解使用

對(duì)于上述注解使用,@Repeatable注解的作用就是使得@RepeaDemo注解可以多個(gè)添加在字段上,而最外層無(wú)須包裹@RepeaDemos注解,當(dāng)然,@RepeaDemos注解任然需要保留,修改如下:

修改@RepeaDemos注解(注意@RepeaDemos注解,必須改為value()才可以):

package com.xiaoxu.tool.demo;

import java.lang.annotation.*;

@Target(value = {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeaDemos {
    RepeaDemo[] value();
}

修改@RepeaDemo注解,增加@Repeatable,參數(shù)為RepeaDemos.class:

package com.xiaoxu.tool.demo;

import java.lang.annotation.*;

@Target(value = {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(RepeaDemos.class)
@Documented
public @interface RepeaDemo {
    String id();
    String name();
}

修改demo類(lèi):

package com.xiaoxu.tool.demo;
import java.lang.reflect.Field;
import java.util.Arrays;
/**
 * @author xiaoxu
 * @date 2022-05-17
 * spring_boot:com.xiaoxu.tool.demo.TestRepeatable
 */
public class TestRepeatable {
//    @RepeaDemos(value = {
//        @RepeaDemo(id = "1001",name = "荔枝"),
//        @RepeaDemo(id = "1003",name = "沃柑")
//    })
    @RepeaDemo(id = "1001",name = "荔枝")
    @RepeaDemo(id = "1003",name = "沃柑")
    private String fruit1;
    @RepeaDemo(id = "1002",name = "葡萄")
    private String fruit2;
    public static void demo1(){
        Class<?> a = TestRepeatable.class;
        Field[] fruits = a.getDeclaredFields();
        Arrays.stream(fruits).forEach(f->{
            if(f.isAnnotationPresent(RepeaDemo.class)){
                RepeaDemo anno = f.getAnnotation(RepeaDemo.class);
                String id = anno.id();
                String name = anno.name();
                System.out.printf("水果id:%s,水果名稱:%s%n",id,name);
            }
        });
    }
    public static void demo2(){
        Class<?> a = TestRepeatable.class;
        Field[] fruits = a.getDeclaredFields();
        Arrays.stream(fruits).forEach(f->{
            if(f.isAnnotationPresent(RepeaDemos.class)){
                RepeaDemos anno = f.getAnnotation(RepeaDemos.class);
                RepeaDemo[] res= anno.value();
                Arrays.stream(res).forEach(r-> System.out.printf("水果id:%s,水果名稱:%s%n",r.id(),r.name()));
            }
            if(f.isAnnotationPresent(RepeaDemo.class)){
                RepeaDemo anno = f.getAnnotation(RepeaDemo.class);
                String id = anno.id();
                String name = anno.name();
                System.out.printf("水果id:%s,水果名稱:%s%n",id,name);
            }
        });
    }
    public static void main(String[] args) {
        demo2();
    }
}

執(zhí)行效果如下:

水果id:1001,水果名稱:荔枝
水果id:1003,水果名稱:沃柑
水果id:1002,水果名稱:葡萄

可見(jiàn),如下兩種方式,獲取的結(jié)果是一致的,其實(shí)@Repeatable注解就是一種語(yǔ)法糖(類(lèi)似于python的裝飾器語(yǔ)法糖等等),本質(zhì)上在java編譯時(shí),使用如下的第2種注解方式,等同于使用第1種:

//1:
@RepeaDemos(value = {
    @RepeaDemo(id = "1001",name = "荔枝"),
    @RepeaDemo(id = "1003",name = "沃柑")
})
//2:
@RepeaDemo(id = "1001",name = "荔枝")
@RepeaDemo(id = "1003",name = "沃柑")

2.3 小結(jié)

1 @Repeatable注解使用前,需先增加一個(gè)注解的屬性值為子注解數(shù)組,且名稱為value()的父注解;

2 @Repeatable注解需要在子注解上標(biāo)注,且@Repeatable注解的值為父注解class;

3 @Repeatable注解本質(zhì)上是一種語(yǔ)法糖。

到此這篇關(guān)于Java的@Repeatable注解使用詳細(xì)解析的文章就介紹到這了,更多相關(guān)@Repeatable注解的使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java并發(fā)編程中的CyclicBarrier線程屏障詳解

    Java并發(fā)編程中的CyclicBarrier線程屏障詳解

    這篇文章主要介紹了Java并發(fā)編程中的CyclicBarrier線程屏障詳解,
    2023-12-12
  • SpringMVC @RequestBody的使用解析

    SpringMVC @RequestBody的使用解析

    這篇文章主要介紹了SpringMVC @RequestBody的使用解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • maven 隱式依賴引起的包沖突解決辦法

    maven 隱式依賴引起的包沖突解決辦法

    這篇文章主要介紹了maven 隱式依賴引起的包沖突解決辦法的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • MyBatis延遲加載實(shí)現(xiàn)步驟詳解

    MyBatis延遲加載實(shí)現(xiàn)步驟詳解

    這篇文章主要介紹了MyBatis延遲加載實(shí)現(xiàn)步驟詳解,? MyBatis中的延遲加載,也成為懶加載,是指在進(jìn)行關(guān)聯(lián)查詢時(shí),按照設(shè)置的延遲規(guī)則推遲對(duì)關(guān)聯(lián)對(duì)象的查詢,延遲加載可以有效的減少數(shù)據(jù)庫(kù)的壓力,需要的朋友可以參考下
    2023-10-10
  • Java使用@Retryable注解實(shí)現(xiàn)HTTP請(qǐng)求重試

    Java使用@Retryable注解實(shí)現(xiàn)HTTP請(qǐng)求重試

    HTTP調(diào)用是Java應(yīng)用與外部API進(jìn)行交互時(shí)重要的訪問(wèn)方式之一,為了確保在遇到臨時(shí)性問(wèn)題時(shí)能自動(dòng)重試,我們可以設(shè)計(jì)一個(gè)靈活的重試機(jī)制,在Java中,我們可以通過(guò)注解來(lái)實(shí)現(xiàn)這一功能,文將介紹如何使用注解@Retryable來(lái)實(shí)現(xiàn)HTTP調(diào)用的重試機(jī)制,需要的朋友可以參考下
    2024-10-10
  • Java模擬實(shí)現(xiàn)ATM機(jī)

    Java模擬實(shí)現(xiàn)ATM機(jī)

    這篇文章主要為大家詳細(xì)介紹了Java模擬實(shí)現(xiàn)ATM機(jī),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • maven中no main manifest attribute的問(wèn)題解決

    maven中no main manifest attribute的問(wèn)題解決

    本文主要介紹了maven中no main manifest attribute的問(wèn)題解決,這個(gè)錯(cuò)誤通常意味著Spring Boot應(yīng)用在啟動(dòng)時(shí)遇到了問(wèn)題,下面就來(lái)具體介紹一下,感興趣的可以了解一下
    2024-08-08
  • java切分字符串的2種方法實(shí)例

    java切分字符串的2種方法實(shí)例

    在我們?nèi)粘9ぷ髦薪?jīng)常遇到截取字符串的需求,下面這篇文章主要給大家介紹了關(guān)于java切分字符串的2種方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 解決java.lang.ClassCastException的java類(lèi)型轉(zhuǎn)換異常的問(wèn)題

    解決java.lang.ClassCastException的java類(lèi)型轉(zhuǎn)換異常的問(wèn)題

    這篇文章主要介紹了解決java.lang.ClassCastException的java類(lèi)型轉(zhuǎn)換異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Calcite使用SQL實(shí)現(xiàn)查詢csv/json文件內(nèi)容

    Calcite使用SQL實(shí)現(xiàn)查詢csv/json文件內(nèi)容

    calcite可以支持文件系統(tǒng)的數(shù)據(jù)源適配, 其實(shí)官方已經(jīng)提供了相應(yīng)的能力, 其支持csv和json的查詢適配,下面我們就來(lái)看看Calcite如何使用SQL實(shí)現(xiàn)查詢csv/json文件內(nèi)容吧
    2025-01-01

最新評(píng)論