作用
1. 用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。
2. 与具体业务无关,也不会影响正常的业务逻辑。
功能
1. 用反射机制来进行校验、赋值等操作。
2. 跟踪代码依赖性,实现替代配置文件功能,如spring mvc的注解。
3. 编译时进行格式检查,如@override。
4. 编译时进行代码生成补全,如lombok插件的@Data。
定义
1. 成员参数只能使用八种基本类型(byte、short、char、int、long、float、double、boolean)和String、Enum、Class、annotations等数据类型,及其数组。
2. 获取类方法和字段的注解信息,只能通过Java的反射技术来获取 Annotation 对象。
3. 注解可以没有定义成员,只做标识。
元注解
元注解是为自定义注解提供的注解。java.lang.annotation提供了四种元注解:
1. @Documented – 注解是否将包含在JavaDoc中
2. @Retention – 什么时候使用该注解
3. @Target – 注解用于什么地方
4. @Inherited – 是否允许子类继承该注解
5. @Repeatable - 是否可重复注解,jdk1.8引入
注解的生命周期
通过@Retention定义注解的生命周期,格式如下:
其中RetentionPolicy的不同策略对应的生命周期如下:
- RetentionPolicy.SOURCE : 仅存在于源代码中,编译阶段会被丢弃,不会包含于class字节码文件中。@Override, @SuppressWarnings都属于这类注解。
- RetentionPolicy.CLASS : 默认策略,在class字节码文件中存在,在类加载的时被丢弃,运行时无法获取到。
- RetentionPolicy.RUNTIME : 始终不会丢弃,可以使用反射获得该注解的信息。自定义的注解最常用的使用方式。
注解的作用范围
通过@Target定义注解作用范围,比如作用于类、属性、或方法等,默认可用于任何地方。格式如下:
@Target(ElementType.TYPE)
Java提供使用反射API读取Annotation的方法包括:
Class.isAnnotationPresent(Class)
Field.isAnnotationPresent(Class)
Method.isAnnotationPresent(Class)
Constructor.isAnnotationPresent(Class)
// 使用反射API读取注解信息
XXX.getAnnotation(Class)
例如:获取User类中定义的@Report注解
// 当注解是一种接口,获取之后可以调用接口方法得到定义的值
Report report = User.class.getAnnotation(Report.class);
int type = report.type();
String level = report.level();