Java注解的玩儿法。
元注解是指注解的注解,包括@Retention @Target @Document @Inherited四种。
呃,看了一眼源码其实8(我截止到今天用的是8,2018/8/1)里面还有 @Repeatable。
先按顺序来分析:
1、@Retention作用
定义注解的保留策略
- @Retention(RetentionPolicy.SOURCE): 注解仅保存在源码阶段,编译和运行时都不会有。
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
- @Retention(RetentionPolicy.CLASS): 注解会在class字节码中存在,运行时不可见。此策略为默认。
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
- @Retention(RetentionPolicy.RUNTIME): 注解会在class字节码文件中存在,在运行时可以通过反射获取到
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
2、@Target: 定义注解的作用目标
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE, // 类,接口,枚举,注解。
/** Field declaration (includes enum constants) */
FIELD, // 字段, 枚举常量。
/** Method declaration */
METHOD, // 方法
/** Formal parameter declaration */
PARAMETER, // 方法参数
/** Constructor declaration */
CONSTRUCTOR, // 构造函数
/** Local variable declaration */
LOCAL_VARIABLE, // 局部变量
/** Annotation type declaration */
ANNOTATION_TYPE, // 注解
/** Package declaration */
PACKAGE, // 包
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER, // 新特性,表示这个 Annotation 可以用在 Type 的声明式前
/**
* Use of a type * * @since 1.8
*/
TYPE_USE // 新特性,表示当前Annotation 可以用在所有使用 Type 的地方(如:泛型,类型转换等)。
}
3、@Documented
表示可以出现在javadoc中,
4、@Inherited
该注解表示子类可以集成加载父类上的注解。但要注意:
1.注解定义在类上面,子类是可以继承该注解的。
2.注解定义在方法上面,子类也可以继承该注解,但是如果子类复写了父类中定义了注解的方法,那么子类将无法继承该方法的注解,也就是说,子类在复写父类中被@Inherited标注的方法时,会将该方法上面的注解覆盖掉
3.Interface的实现类(implements实现)无法继承接口中所定义的被@Inherited标注的注解
@Inherited的总结来自:
CShawnX:Java和Android中的注解
5、@Repeatable 可以重复注解
在之前,相同的注解在同一个位置只能使用一次, java8 引入了重复注解机制。可以让一个注解在一个位置引用多次。例如:
@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
String role default"";
}
@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{
}
表示这个SuperMan 可以是三种角色,artist,coder,PM。
上面代码中,用@Repeatable注解了注解Person,而其括号内的Persons.class表示为一个注解容器。
按照规定,它里面必须要有一个 value 的属性,属性类型是一个被 @Repeatable 注解过的注解数组,注意它是数组。
注解怎么玩儿?
注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。
注解有许多用处,主要如下:
- 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息
- 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它相应处理。
- 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取
玩儿法一
java预置了一些注解,可以通过这些注解,对代码进行描述。达到某种目的。
@Deprecated、@Override、@SuppressWarnings、@SafeVarargs、@FunctionalInterface
玩儿法二
那就是自己定义一些注解了。
通过反射,获得相关的注解,并未目标增加一系列附加的处理操作。因为正像官方描述:注解对于代码的运行效果没有直接影响。但是我们可以为其增强啊。
getAnnotation()或者getAnnotations()可以获得目标的注解对象或者所有注解的数组。再根据这些注解对象以及其成员属性。
可以据此为其编写外部能力。
应用场景
日志、测试类、Ioc、功能增强等。