• 深入理解Java中的注解


    1. 元注解@Inherited继承

    package com.example.demo;
    
    import java.lang.annotation.*;
    import java.util.Arrays;
    
    public class Test {
        public static void main(String[] args) {
            Annotation[] superAnnos = SuperClass.class.getAnnotations();
            System.out.println(Arrays.toString(superAnnos));
            Annotation[] childAnnos = ChildClass.class.getAnnotations();
            System.out.println(Arrays.toString(childAnnos));
        }
    }
    
    @Target(value = ElementType.TYPE)
    @Retention(value = RetentionPolicy.RUNTIME)
    @Inherited // 声明注解具有继承性
    @interface InheritedAnno {
        String value() default "InheritedAnno";
    }
    
    @InheritedAnno
    class SuperClass{
    
    }
    class ChildClass extends SuperClass{ // 子类可以继承父类的注解
    
    }
    
    

    2.属性和方法注解的继承性

    在属性和方法上的注解不同于在类上的注解,它们的特殊性在于如果子类继承的方法在父类中有注解,那么这些方法和属性是可以继承下来的。但是如果子类的方法如果进行了重写,那么重写后的方法是不会有父类对应方法中的注解的。如果是父接口方法上面带有注解, 因为接口方法必须要实现(相当于重写),所以实现父接口的方法上不能继承注解。

    package com.example.demo;
    
    import java.lang.annotation.*;
    import java.util.Arrays;
    
    public class Test {
        public static void main(String[] args) throws Exception{
            Annotation[] field1Annos = ChildClass.class.getField("field1").getAnnotations();
            System.out.println(Arrays.toString(field1Annos));
            Annotation[] method1Annos = ChildClass.class.getMethod("method1").getAnnotations();;
            System.out.println(Arrays.toString(method1Annos));
            Annotation[]  method1OverrideAnnos = ChildClass2.class.getMethod("method1").getAnnotations();
            System.out.println(Arrays.toString(method1OverrideAnnos));
        }
    }
    
    @Target(value = ElementType.METHOD)
    @Retention(value = RetentionPolicy.RUNTIME)
    @interface MethodAnno {
        String value() default "AMethod";
    }
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface FieldAnno{
        String value() default  "AField";
    }
    
    class SuperClass{
        @FieldAnno
        public int field1 = 100;  // 必须使用public,否则反射查找子类该字段时会抛出找不到的异常
        @MethodAnno
        public void method1(){
            System.out.println("super.method1");
        }
    }
    class ChildClass extends SuperClass{ // 子类可以继承父类的注解
    
    }
    class ChildClass2 extends SuperClass{
        @Override
        public void method1(){
            System.out.println("child.method1");
        }
    }
    

    3. ElementType.TYPE的注解

    该种注解可以用来注解其它注解,很多人认为这时一种注解的合并,其实这种看法时错误的。

    // @SpringBootApplication的定义
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    }
    /* 使用@SpringBootApplication,其实等价于使用了下面的四个注解:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan、@SpringBootApplication。
    从java层面的原理来讲,并不是@SpringBootApplication内部包含(或者认为合并了)另外的三个注解,而是另外的三个注解修饰@SpringBootApplication这个注解,如果要获取其它三个注解的值,那么必须通过SpringBootApplication.class.getAnnotations()的方法获取。
    */
    
    package com.example.demo;
    
    import java.lang.annotation.*;
    import java.util.Arrays;
    
    @AnnoC
    public class Test {
        public static void main(String[] args) throws Exception{
            Annotation[] annos = Test.class.getAnnotations();
            System.out.println(Arrays.toString(annos));
            AnnoC annoC = (AnnoC)annos[0];
            System.out.println(annoC.valueC());
            AnnoB annoB = AnnoC.class.getAnnotation(AnnoB.class);
            System.out.println(annoB.valueB());
            Annotation [] annos2 = AnnoC.class.getAnnotations();
            System.out.println(Arrays.toString(annos2));
    
    
        }
    }
    
    @Target(value = ElementType.TYPE) //TYPE可以用于注解其它注解
    @Retention(value = RetentionPolicy.RUNTIME)
    @interface AnnoA{
        String valueA() default "A";
    }
    
    @Target(ElementType.TYPE) 
    @Retention(RetentionPolicy.RUNTIME)
    @interface AnnoB{
        String valueB() default  "B";
    }
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @AnnoA
    @AnnoB
    @interface AnnoC{ // AnnoC上有四个注解,AnnoC也是一个类
        String valueC() default  "C";
    }
    
  • 相关阅读:
    20年美亚杯WRITE UP
    博客搬迁
    前端工程化1-模块
    移动端(h5)工具函数--视口适配(viewport)
    Understanding ES6 Modules(译)
    手写http请求并发、重试、超时函数
    两道编程题引发的思考
    前端基础走查(六):异步任务和事件循环
    vue 本地图片批量下载以及压缩成zip文件下载
    mybatis generator逆向工程
  • 原文地址:https://www.cnblogs.com/memo20/p/13121634.html
Copyright © 2020-2023  润新知