zoukankan      html  css  js  c++  java
  • 元注解之@Repeatable

    简介

    @Repeatable注解从JDK 1.8开始引入,为了解决注解不能在同一个地方重复使用而出现的。在JDK 1.8以前,下面这段代码将不能通过编译。

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Identity {
    
        String value();
    }
    
    // 不能重复使用
    @Identity("父亲")
    @Identity("教师")
    public class RepeatableTest {
    
    }
    
    

    使用

    先定义注解

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Repeatable(Identities.class)
    @Documented
    public @interface Identity {
    
        String value();
    }
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Identities {
    
        Identity[] value();
    }
    
    

    为了使得@Identity注解可以重复使用,需要注意以下几点。

    • 在定义时用@Repeatable标记一个容器注解@Identities
    • 该容器注解@Identities必须要声明一个value方法,并且返回值是一个Identity[]类型,否则编译报错。

    测试类

    @Identity("父亲")
    @Identity("教师")
    public class RepeatableTest {
    
        public static void main(String[] args) {
            // 获取注解信息
            // 值得注意的是参数传的是Identities.class,而不是Identity.class。
            // 原因看下面原理介绍
            Identities identitiesAnnotation = RepeatableTest.class.
                getAnnotation(Identities.class);
            Identity[] identities = identitiesAnnotation.value();
            Arrays.stream(identities).forEach(identity -> 
               System.out.println(identity.value()));
        }
    }
    

    原理

    如果我们将编译后的RepeatableTest.class文件反编译下,将得到以下源代码。

    @Identities({@Identity("父亲"), @Identity("教师")})
    public class RepeatableTest {
        public RepeatableTest() {
        }
        
        // 省略main方法
    }
    

    可以看到重复使用@Identity注解其实是一个语法糖,这也是为什么上面getAnnotation方法传的参数是Identities.class的原因。继续使用Class类提供的方法做检测。

    @Identity("父亲")
    @Identity("教师")
    public class RepeatableTest {
    
        public static void main(String[] args) {
            // 返回false
            System.out.println(RepeatableTest.class.isAnnotationPresent(Identity.class));
            // 返回null
            System.out.println(RepeatableTest.class.getAnnotation(Identity.class));
            // 由此可见RepeatableTest类中确实没有被Identity直接注解。
            
            // 另外一种简便的方法获取注解信息
            // 使用getAnnotationsByType方法, 此方法为JDK 1.8新增
            Identity[] identities = RepeatableTest.class
                .getAnnotationsByType(Identity.class);
            Arrays.stream(identities).forEach(identity ->
                    System.out.println(identity.value()));
    
            Identities[] identitiesAnnotation = RepeatableTest.class.
                getAnnotationsByType(Identities.class);
            // 输出父亲
            System.out.println(identitiesAnnotation[0].value()[0].value());
        }
    }
    
  • 相关阅读:
    如何成为伟大的程序员
    程序员如何增加收入
    一个阿里巴巴码农的六年回眸
    效仿盖茨:PPstream创始人的心路历程
    程序员的工作环境与效率
    软件级负载均衡器(LVS/HAProxy/Nginx)的特点简介和对比
    技术人员创业后就不再适合继续编码了
    互联网行业持续交付的经验
    11 款用于优化、分析源代码的Java工具
    常用 Java 静态代码分析工具的分析与比较
  • 原文地址:https://www.cnblogs.com/wt20/p/11801814.html
Copyright © 2011-2022 走看看