java的元注解
注解在jdk1.5时候出现,在jdk1.8的时候使用的人数逐渐增多。
在java中有四个元注解:
@Documented
该注解会在生成javadoc的时候在javadoc生成文档,jdk1.8的源码如下
/**
* Indicates that annotations with a type are to be documented by javadoc
* and similar tools by default. This type should be used to annotate the
* declarations of types whose annotations affect the use of annotated
* elements by their clients. If a type declaration is annotated with
* Documented, its annotations become part of the public API
* of the annotated elements.
*
* @author Joshua Bloch
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
下面时经过翻译的注释
指示默认情况下,javadoc和类似工具将记录具有类型的注释。此类型应用于注释其注释会影响客户端使用注释元素的类型的声明。如果使用Documented对类型声明进行注释,则其注释将成为注释元素的公共API的一部分。
@Target
该注解决定了你的自定义注解的作用范围,源码如下,由于
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
可以看到@Target
这个注解中有个value参数,该参数是个ElementType
类型的枚举数组,下面来看下ElementType
这个枚举。
value参数是注解中的默认参数,在只给value赋值的地方value=语句可以省略
public enum ElementType {
// 表示注解可以使用在类上
TYPE,
// 表示注解可以使用在字段上
FIELD,
// 表示注解可以使用在方法上
METHOD,
// 表示注解可以使用在参数上
PARAMETER,
// 表示注解可以使用在构造方法上
CONSTRUCTOR,
// 表示注解可以使用在局部变量上
LOCAL_VARIABLE,
// 表示注解可以使用在注解类上
ANNOTATION_TYPE,
// 表示注解可以使用在包上
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
最下面两个不常用。
@Retention
该注解决定了你的注解在何时生效。
/**
* Indicates how long annotations with the annotated type are to
* be retained. If no Retention annotation is present on
* an annotation type declaration, the retention policy defaults to
* {@code RetentionPolicy.CLASS}.
*
* <p>A Retention meta-annotation has effect only if the
* meta-annotated type is used directly for annotation. It has no
* effect if the meta-annotated type is used as a member type in
* another annotation type.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.2 @Retention
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
注释的百度翻译如下
指示带批注类型的批注要保留多长时间。如果批注类型声明上不存在保留批注,则保留策略默认为保留策略.CLASS.
只有当元注释类型直接用于注释时,保留元注释才有效。如果元注释类型被用作另一个注释类型中的成员类型,则没有效果。
简单说明一下就是表示你的注解在运行时或者源文件中生效,只有当value为RUNTIME
的时候才会在运行时生效。
@Retention
这个注解中的value值为RetentionPolicy
类型的枚举,下面来看下@Retention
注解的源码
public enum RetentionPolicy {
// 在编译时会被丢弃
SOURCE,
// 注解会保留在类文件中
CLASS,
// 注解会在运行时被保留,因此可以使用反射读取到该注解
RUNTIME
}
一般注解需要实现某种配置或者功能都需要运行时使用反射去动态读取注解,因此使用的比较多的是RUNTIME
。
@Inherited
该注解所标注的注解是可以被子类继承的。
/**
* Indicates that an annotation type is automatically inherited. If
* an Inherited meta-annotation is present on an annotation type
* declaration, and the user queries the annotation type on a class
* declaration, and the class declaration has no annotation for this type,
* then the class's superclass will automatically be queried for the
* annotation type. This process will be repeated until an annotation for this
* type is found, or the top of the class hierarchy (Object)
* is reached. If no superclass has an annotation for this type, then
* the query will indicate that the class in question has no such annotation.
*
* <p>Note that this meta-annotation type has no effect if the annotated
* type is used to annotate anything other than a class. Note also
* that this meta-annotation only causes annotations to be inherited
* from superclasses; annotations on implemented interfaces have no
* effect.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.3 @Inherited
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
注释的百度翻译如下
指示自动继承批注类型。如果在注释类型声明上存在继承的元注释,并且用户在类声明上查询注释类型,而该类声明对此类型没有注释,则将自动在类的超类中查询注释类型。将重复此过程,直到找到此类型的注释,或到达类层次结构(对象)的顶部。如果没有超类具有此类型的注释,则查询将指示所讨论的类没有此类注释。
请注意,如果注释类型用于注释类以外的任何内容,则此元注释类型无效。还要注意,这个元注释只会导致注释从超类继承;对实现接口的注释没有影响。
简单的说就当你的自定义注解的作用于为RUNTIME
时,你把@Inherited
加载自己的注解上,在自己的父类上加上自定义注解,可以通过反射获取子类的类模板,使用getAnnotations()
方法获取父类上的注解。