ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

注解学习完整篇

2022-05-15 00:34:20  阅读:150  来源: 互联网

标签:school china value 学习 完整篇 注解 com Hello



import java.lang.annotation.*;
import java.util.Arrays;

/**
 * 注解
 * 我个人认为其实就是接口,从接口变过来的,只不过他不可以定义方法,
 * 通过@interface限制了它包含了它独有的语法
 *
 * 一 要点
 *  1 注解属于静态类,其中内部类属于静态类
 *  2 默认继承了java.lang.annotation.Annotation接口,不可以继承其他接口(类似与枚举类默认继承了Enum类一样)
 *  3 成员数量(2个) 成员变量和静态内部类都是public修饰,没有构造器,代码块,方法
 *  4 创建注解对象,访问注解成员变量
 *      注解的实例不可通过new的方式,也不可以过Class对象的newInstance()的方式去获取只能通过Class对象的如下方法获取
 *                A	getAnnotation(Class<A> annotationClass)  获得多个重复注解注解对象时将报错
 *     Annotation[]	getAnnotations() 获取该类所有的注解(包括来自父类)
 *                A	getDeclaredAnnotation(Class<A> annotationClass) 获得多个重复注解注解对象时将报错
 *     Annotation[]	getDeclaredAnnotations()  返回多个类型的注解,只能是Annotation[]
 *              A[]	getAnnotationsByType(Class<A> annotationClass) 获取多个相同注解对象,可来自继承
 *              A[]	getDeclaredAnnotationsByType(Class<A> annotationClass) 取多个相同注解对象,完全来自本类的声明
 *   5 getAnnotation和getDeclaredAnnotation访问不存在的注解将报错
 二 注解的定义
 1  @Target 注解修饰,指定该注解可修饰的程序元素类型
 2  @Retention 指定该注解的生命周期
 3  default指定默认值
 4  有且一个成员变量名为value时,可如此使用@Anno("tom")
 5  当成员变量name的类型为数组,但给赋一个这样的数组元素时{"tom"},可如此@Anno(name = "tom")

 三 其他三个元注解可添加如下注解:
     @Documented 文档元注解
     @Inherited 所修饰的注解只能类继承,不可通过接口继承,子类的@Xxx注解会覆盖父类的@Xxx注解信息
     @Repeatable(修饰的子注解必须使用该注解指定父容器.class)

 ElementType枚举类有如下实例:(常用的程序元素: 包,注解,类,常量,构造器,形参,局部变量,)
 PACKAGE,ANNOTATION_TYPE,TYPE,FIELD,METHOD,CONSTRUCTOR,LOCAL_VARIABLE,PARAMETER,
  TYPE_USE(1.8),TYPE_PARAMETER(1.8),MODULE(9)

 RetentionPolicy枚举类有如下实例 SOURCE,CLASS,RUNTIME(生命周期从小到大)
 四  类型注解: 可以使用在任何地方出现的类型前面(TYPE_PARAMETER,TYPE_USE)
    1   创建对象
    2   类型转换
    3   使用implements实现接口,extends继承类
    4   throws 抛出异常
三 定义重复注解(Repeatable)
 1  定义子注解Hello和容器注解Hellos
 2  通过在子注解上生命@Repeatable(Hellos.class)并指定容器注解
 3 容器注解的生命周期必须大于等于子注解
 4 容器定义子容器数组时,必须指定value为变量名,子容器的上的注解和只能比容器注解多一个(@Repeatable)
 5 当多个重复注解修饰同一个元素时,应当获取容器注解对象content,通过content去访问多个重复注解
 (因为你无法通过getAnnotation(Class)和getDeclaredAnnotation(Class)来获取每个子注解对象
 因为重复注解只是表象,这多个重复注解其实会作为容器注解的数组对象存在,最后只存在编译后只存在容器注解)
 比如
 @Hello("a")
 @Hello("b")
 public class Test{}
 最后成了这样
 @Hellos({@Hello("a"),@Hello("b")})
 public class Test{}
 因此当出现重复注解后把它们合成一个注解,再去判断如何获取注解对象,就不会迷茫了

 */


//定义容器注解Hellos
@Inherited
@Documented
@Target( ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Hellos{
    Hello[] value();
}
//定义子注解Hello
@Documented
@Repeatable(Hellos.class)
@Target( ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Hello {
    String value();
}

//定义注解World
@Inherited
@Target( ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface World{
    String value() default "World的默认信息";
}
@World("World-1")
@Hello("Hello-1")
class China  {}

@World("World-2")
@Hello("Hello-2")
@Hello("Hello-3")
@Hello("Hello-4")
public  class 注解  extends  China  {
    public static   void main(String[] args) throws  Exception{
/**
 * 现在对如下这六个方法进行测试,编写了6个对应的静态方法
 *                A    getAnnotation(Class<A> annotationClass)  获得多个重复注解注解对象时将报错
 *     Annotation[]    getAnnotations() 获取该类所有的注解(包括来自父类)
 *                A    getDeclaredAnnotation(Class<A> annotationClass) 获得多个重复注解注解对象时将报错
 *     Annotation[]    getDeclaredAnnotations()  返回多个类型的注解,只能是Annotation[]
 *              A[]    getAnnotationsByType(Class<A> annotationClass) 获取多个相同注解对象,可来自继承
 *              A[]    getDeclaredAnnotationsByType(Class<A> annotationClass) 取多个相同注解对象,完全来自本类的声明
 */
        //获取本类的Class对象,注意: forName要引用完整的包名
       Class clazz = Class.forName("com.china.school.oop.注解");

        //hello实例其实是父类China类的@Hello注解对象,这说明了@Hello注解继承性
        // 本类也声明了3个Hello注解,他们最终合并成Hellos注解对象(class文件里)
        //以后看到多个重复注解修饰同一个元素,就把他们想象成一个容器注解就不会乱。
        Hello hello = (Hello)clazz.getAnnotation(Hello.class);
        System.out.println(hello.value());// Hello-1

        Hellos hellos = (Hellos) clazz.getAnnotation(Hellos.class);
        System.out.println(Arrays.toString(hellos.value()));
        //本例可以很好的解释上面的疑惑,输出结果如下
        //[@com.china.school.oop.Hello(value="Hello-2"),
        // @com.china.school.oop.Hello(value="Hello-3"),
        // @com.china.school.oop.Hello(value="Hello-4")]

        World world = (World)clazz.getDeclaredAnnotation(World.class);
        System.out.println(world.value());
        //输出结果: World-2,获取本类声明的@World注解对象

        Annotation[] anns = clazz.getAnnotations();
        System.out.println(Arrays.toString(anns));
        //获取到了数组中包含三个对象,一个本类的@World对象,一个父类的@Hello对象
        //再一个本类的@Hellos容器对象
        //[@com.china.school.oop.World(value="World-2"),
        // @com.china.school.oop.Hello(value="Hello-1"),
        // @com.china.school.oop.Hellos(
        // value={@com.china.school.oop.Hello(value="Hello-2"),
        // @com.china.school.oop.Hello(value="Hello-3"),
        // @com.china.school.oop.Hello(value="Hello-4")})]

        Annotation[] anns2 = clazz.getDeclaredAnnotations();
        System.out.println(Arrays.toString(anns2));
        //获取到了数组中包含2个对象,一个本类的@World对象,再一个本类的@Hellos容器对象(它又包含了3个@Hello对象)
        //[@com.china.school.oop.World(value="World-2"),
        // @com.china.school.oop.Hellos(
        // value={@com.china.school.oop.Hello(value="Hello-2"),
        // @com.china.school.oop.Hello(value="Hello-3"),
        // @com.china.school.oop.Hello(value="Hello-4")})]

        Hello[] helloArr1 = (Hello[])clazz.getDeclaredAnnotationsByType(Hello.class);
        System.out.println(Arrays.toString(helloArr1));
        //该数组中都是本类的3个重复注解,虽然父类China中也声明了@Hello,但被子类的@Hello给覆盖了
        //如果@Hello注解的定义中去掉@Inherited注解,还是输出3个@Hello对象
        //也就是说获取重复注解永远都是计算本类的声明的个数
        //[@com.china.school.oop.Hello(value="Hello-2"),
        // @com.china.school.oop.Hello(value="Hello-3"),
        // @com.china.school.oop.Hello(value="Hello-4")]

        var anonymous = new 注解(){};
        Hello[] helloArr2 = (Hello[])anonymous.getClass().getAnnotationsByType(Hello.class);
        System.out.println(Arrays.toString(helloArr2));
        //先创建了一个匿名内部类对象anonymous,因为该匿名内部类肯定没有,也没办法声明@Hello注解
        // 通过这个anonymous的Class对象的getAnnotationsByType()获取父类的@Hello重复注解对象,结果如下
        //[@com.china.school.oop.Hello(value="Hello-2"),
        // @com.china.school.oop.Hello(value="Hello-3"),
        // @com.china.school.oop.Hello(value="Hello-4")]

    }
}

输出结果如下:  

Hello-1
[@com.china.school.oop.Hello(value="Hello-2"), @com.china.school.oop.Hello(value="Hello-3"), @com.china.school.oop.Hello(value="Hello-4")]
World-2
[@com.china.school.oop.World(value="World-2"), @com.china.school.oop.Hello(value="Hello-1"), @com.china.school.oop.Hellos(value={@com.china.school.oop.Hello(value="Hello-2"), @com.china.school.oop.Hello(value="Hello-3"), @com.china.school.oop.Hello(value="Hello-4")})]
[@com.china.school.oop.World(value="World-2"), @com.china.school.oop.Hellos(value={@com.china.school.oop.Hello(value="Hello-2"), @com.china.school.oop.Hello(value="Hello-3"), @com.china.school.oop.Hello(value="Hello-4")})]
[@com.china.school.oop.Hello(value="Hello-2"), @com.china.school.oop.Hello(value="Hello-3"), @com.china.school.oop.Hello(value="Hello-4")]
[@com.china.school.oop.Hello(value="Hello-2"), @com.china.school.oop.Hello(value="Hello-3"), @com.china.school.oop.Hello(value="Hello-4")]

标签:school,china,value,学习,完整篇,注解,com,Hello
来源: https://www.cnblogs.com/runwithtime/p/16272046.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有