Java -- 元注解

元注解 就是 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 的作用 -- 被它标注的注解,会被子类继承

end

评论

新增邮件回复功能,回复将会通过邮件形式提醒,请填写有效的邮件!