java8元注解解析

JDK1.5开始引入了注解的概念,并在1.5的版本中提供了4个元注解@Docmented 、@Target、@Retention 和@Inherited。1.8又引入了两个新的注解@Native和@Repeatable。本文主要基于1.8版本的注解展开。

注解与反射机制

前面经过反编译后,我们知道Java所有注解都继承了Annotation接口,也就是说 Java使用Annotation接口代表注解元素,该接口是所有Annotation类型的父接口。
同时为了运行时能准确获取到注解的相关信息,Java在java.lang.reflect 反射包下新增了AnnotatedElement接口,它主要用于表示目前正在 VM 中运行的程序中已使用注解的元素,通过该接口提供的方法可以利用反射技术地读取注解的信息,如反射包的Constructor类、Field类、Method类、Package类和Class类都实现了AnnotatedElement接口,它简要含义如下(更多详细介绍可以看 深入理解Java类型信息(Class对象)与反射机制):

 Class:类的Class对象定义   
 Constructor:代表类的构造器定义   
 Field:代表类的成员变量定义 
 Method:代表类的方法定义   
 Package:代表类的包定义

下面是AnnotatedElement中相关的API方法,以上5个类都实现以下的方法

返回值 方法名称 说明
getAnnotation(Class annotationClass) 该元素如果存在指定类型的注解,则返回这些注解,否则返回 null。
Annotation[] getAnnotations() 返回此元素上存在的所有注解,包括从父类继承的
boolean isAnnotationPresent(Class annotationClass) 如果指定类型的注解存在于此元素上,则返回 true,否则返回 false。
Annotation[] getDeclaredAnnotations() 返回直接存在于此元素上的所有注解,注意,不包括父类的注解,调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响,没有则返回长度为0的数组

元注解

@Target

该注解用来约束注解的作用域,ElementType为其作用域的枚举类。若未指定作用域,则默认可以用于任何元素上。也可以多个值使用,如@Target(value={CONSTRUCTOR, FIELDE})
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();
}

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 */
      /** java8新加入,表示该注解可以用于类型参数声明*/
    TYPE_PARAMETER,

    /** Use of a type @since 1.8  */
      /** java8新加入,表示该注解可以用于类型使用声明*/
    TYPE_USE

这里主要说明一下TYPE_USE,类型注解用来支持在Java的程序中做强类型检查,配合第三方插件工具(如Checker Framework),可以在编译期检测出runtime error(如UnsupportedOperationException、NullPointerException异常),避免异常延续到运行期才发现,从而提高代码质量,这就是类型注解的主要作用。总之Java 8 新增加了两个注解的元素类型ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER ,通过它们,我们可以把注解应用到各种新场合中。

@Retention

该注解用来约束注解的声明周期。声明周期的定义为枚举RetentionPolicy。java1.5引入

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     * 源码级别。注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
     */
    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文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机中),请注意,当注解未定义Retention值时,默认值是CLASS,如Java内置注解,@Override、@Deprecated、@SuppressWarnning等
     */
    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
     * 运行时级别。注解信息将在运行期(JVM)也保留,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息),如SpringMvc中的@Controller、@Autowired、@RequestMapping等
     */
    RUNTIME
}

@Documented

jdk1.5引入。被修饰的注解会生成到javadoc中,可以使用javadoc命令生成文档。

@Inherited

jdk1.5引入。可以让注解被继承,但这并不是真的继承,只是通过使用@Inherited,可以让子类Class对象使用getAnnotations()获取父类被@Inherited修饰的注解

@Native

java8引入。作用域为代码块,源码级别,编译器就会被丢弃。待补充。。。

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Native {
}

@Repeatable

java8引入。可使用重复注解。运行时。待补充。。。

你可能感兴趣的:(JDK)