元注解 就是 Java标准库中 原生的注解,有点类似于 Java类 中的 Object,由于添加在其他注解上
Java总共有四个元注解,他们的功能如下:
- @Target(ElementType.ANNOTATION_TYPE):指定该注解可以用于注解类、接口或枚举类型。
- @Retention(RetentionPolicy.RUNTIME):指定该注解的保留策略,即在程序运行时也可以访问到该注解。
- @Documented:指定该注解应该被包含在 Java 文档中。
- @Inherited:指定该注解可以继承自父类。
下面分别介绍四个元注解的使用方式
@Target(ElementType.ANNOTATION_TYPE)
通过该注解,我们可以传入参数来指定,被标注的注解能用在哪
传入的参数是ElementType枚举,起源码如下
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,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
每个枚举常量上都有注释
比如:
TYPE是只能加在类上
FIELD是只能加在属性上
见名知意
@Retention(RetentionPolicy.RUNTIME)
该注解规定了被标注的注解的保留策略,
同样,我们出入其提供的 枚举类RetentionPolicy 进行指定
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* 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,
/**
* 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
}
其中的RUNTIME表示 在程序运行时也可以访问到该注解,这也是我们最常用的
@Documented
该注解由于指示被 标注的注解 本身应该被包含在JavaDoc中
JavaDoc是Java编程语言中的一种文档格式,它用于描述类、方法、字段等程序元素的用途、参数、返回值等信息
@Documented
注解可以用于任何注解上,指示该注解本身应该被包含在JavaDoc中,而不是仅仅包含被注解的元素。
@Inherited
这个比较绕,我们举个例子
首先这是一个加了 @Inherited 的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface HasInherited {
}
这个是没加 @Inherited 的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoInherited {
}
接下来是两个类,一个父类,一个子类
public class Father {
}
public class Child extends Father{
}
接着运行一个测试类
public class Test {
public static void main(String[] args) {
// 打印父类注解信息
Annotation[] fatherAnnotations = Father.class.getAnnotations();
System.out.println("------- 父类 Father 信息 --------");
System.out.println("父类注解个数:" + fatherAnnotations.length);
for (Annotation fa : fatherAnnotations) {
System.out.println(fa.annotationType().getSimpleName());
}
// 打印子类注解信息
Annotation[] childAnnotations = Child.class.getAnnotations();
System.out.println("------- 子类 Child 信息 --------");
System.out.println("子类注解个数:" + childAnnotations.length);
for (Annotation ca: childAnnotations) {
System.out.println(ca.annotationType().getSimpleName());
}
}
}
当 父类Father 上加了 @HasInherited 注解,如下
@HasInherited
public class Father {
}
那么子类也会被加上 @HasInherited 注解
而如果 父类Father 上加了 @NoInherited 注解,如下
@NoInherited
public class Father {
}
那么 子类 就不会被加上 @NoInherited 注解
上面演示的就是 @Inherited 的作用 -- 被它标注的注解,会被子类继承