概念
注解是Java语言5.0版本开始支持加入源代码的特殊语法元数据(描述数据的数据)有点像Class(描述类的类)
要自定义注解,必须先了解Java提供的几个基本的元注解及其相关的语法
Java的几个元注解
- @Target
- @Retention
- @Inherited
- @Documented
@Target
SourceCode:
package java.lang.annotation;
/**
* Defines a meta-annotation for determining what {@link ElementType}s an
* annotation can be applied to.
*
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
@Target能够指定注解作用的范围,注解、构造器、域、局部变量、方法、包、参数、类、接口、枚举它有以下8个值
ElementType | 备注 |
---|---|
ANNOTATION_TYPE | 作用于注解类型 |
CONSTRUCTOR | 作用于构造器 |
FIELD | 作用于域 |
LOCAL_VARIABLE | 作用于局部变量 |
METHOD | 作用于方法 |
PACKAGE | 作用于包 |
PARAMETER | 作用于参数 |
TYPE | 作用于描述类、接口、枚举 |
如果自定义的注解没有指定@Target,默认该注解可以使用在上述所有范围,如果存在@Target则编译器会强制实施相应的使用规则,例如如果@Target指定是ANNOTATION_TYPE
@Target(ElementType.ANNOTATION_TYPE)
public @interface MyAnnotation {
...
}
则MyAnnotation只能用在注解上,不能用在其他范围
@MyAnnotation //right
public @interface AnotherAnnotation{
...
}
@MyAnnotation //compile error
public class MyClass{
....
}
如果要作用于多个范围,使用大括号中间用逗号隔开,注意括号内不能存在相同的ElementType值否则编译错误。eg如下
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyAnnotation {
...
}
@Retention
SourceCode:
package java.lang.annotation;
/**
* Defines a meta-annotation for determining the scope of retention for an
* annotation. If the retention annotation is not set {@code
* RetentionPolicy.CLASS} is used as default retention.
*
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
@Retention指定注解的生命周期即保留的时间,如果未声明@Retention默认使用的保留策略为RetentionPolicy.CLASS
RetentionPolicy | 备注 |
---|---|
CLASS | 存在源文件、编译的Class字节码中,运行时VM不在保留 |
RUNTIME | 存在源文件、编译的Class字节码中,运行时VM会保存,且能通过反射获取注解 |
SOURCE | 保留在源文件中,编译器会丢弃 |
@Inherited
SourceCode:
package java.lang.annotation;
/**
* Defines a meta-annotation for indicating that an annotation is automatically
* inherited.
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
分析源码可知@Inherited只能修饰注解,它表示该注解类型被自动继承,如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行直到这个标注类型被找到,或者是查询到顶层的父类
@Documented
SourceCode:
package java.lang.annotation;
/**
* Defines a meta-annotation for indicating that an annotation is documented and
* considered part of the public API.
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Documented:表示拥有该注解的元素可通过javadoc此类的工具进行文档化。该类型应用于注解那些影响客户使用带注(comment)的元素声明的类型。如果类型声明是用Documented来注解的,这种类型的注解被作为被标注的程序成员的公共API