Annotation

发布时间 2023-12-01 16:23:47作者: anpeiyong

概述

The common interface extended by all annotation types.
Note that an interface that manually extends this one does not define an annotation type.
Also note that this interface does not itself define an annotation type.

Annotation被所有annotation类型 继承

注意:手动继承 Annotation的接口 不是 一个annotation类型 (eg: class Test implements Annotation); 

注意:Annotation 本身不定义为 一个annotation类型;

 

More information about annotation types can be found in section 9.6 of The Java Language Specification.

The {@link java.lang.reflect.AnnotatedElement} interface discusses compatibility concerns when evolving an annotation type from being non-repeatable to being repeatable.

 

public interface Annotation {
        boolean equals(Object obj);
        int hashCode();
        String toString();
        // Returns the annotation type of this annotation.
        Class<? extends Annotation> annotationType();
    }

 

基础 

JDK1.5版本开始引入的一个特性;

对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解;

 

作用有以下四方面:

  生成文档,通过代码里标识的元数据生成javadoc文档。

  编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证。

  编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码

  运行时动态处理,运行时通过代码里标识的元数据动态处理,例如使用反射注入实例

 

Java 1.5开始自带的标准注解

  @Override:表示当前的方法定义将覆盖父类中的方法

  @Deprecated:表示代码被弃用,如果使用了被@Deprecated注解的代码则编译器将发出警告

  @SuppressWarnings:表示关闭编译器警告信息

 

JDK 1.5中提供了4个标准的元注解

  @Target

    描述注解的使用范围(即:被修饰的注解可以用在什么地方);

    用于修饰 packages、types(类、接口、枚举、注解类)、类成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数),在定义注解类时使用了@Target 能够更加清晰的知道它能够被用来修饰哪些对象,它的取值范围定义在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
}

  

  @Reteniton

    描述注解保留的时间范围(即:被描述的注解在它所修饰的类中可以被保留到何时) ;

    Reteniton注解用来限定那些被它所注解的注解类在注解到其他类上以后,可被保留到何时,一共有三种策略,定义在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
}

  

  @Documented

    在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息

  @Inherited

    被它修饰的Annotation将具有继承性。

    如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。

 

本质

@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    String desc();

}



@MyAnnotation(desc = "my annotation")
public class TestAnnotation {

    public static void main(String[] args) {

        MyAnnotation myAnnotation = TestAnnotation.class.getDeclaredAnnotation(MyAnnotation.class);
        System.out.println(myAnnotation.desc());
    }

}


字节码:
 0 ldc #2 <annotationtest/TestAnnotation>
 2 invokevirtual #3 <java/lang/Class.getDeclaredAnnotations>
 5 astore_1
 6 ldc #2 <annotationtest/TestAnnotation>
 8 ldc #4 <annotationtest/MyAnnotation>
10 invokevirtual #5 <java/lang/Class.getDeclaredAnnotation>
13 checkcast #4 <annotationtest/MyAnnotation>
16 astore_2
17 getstatic #6 <java/lang/System.out>
20 aload_2
21 invokeinterface #7 <annotationtest/MyAnnotation.desc> count 1     // myAnnotation.desc() 使用的是invokeinterface,表明 @MyAnnotation是一个接口
26 invokevirtual #8 <java/io/PrintStream.println>
29 return

  

  自定义annotation 是一个继承自Annotation 的接口

 

annotation支持继承么?

不能使用关键字extends来继承某个@interface,但注解在编译后,编译器会自动继承java.lang.annotation.Annotation接口;

被注解的子类继承父类注解可以用@Inherited: 如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解;

如何被实例化?

@MyAnnotation实例 是个JDK动态代理对象,sun.reflect.annotation.AnnotationInvocationHandler 就是代理对象调用的handler