注解学习完整篇
作者:互联网
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