美文网首页
java 注解枚举的底层实现

java 注解枚举的底层实现

作者: hehehehe | 来源:发表于2020-11-09 20:33 被阅读0次
    注解
    {InterfaceModifier} @ interface Identifier AnnotationTypeBody
    
    接口修饰符 @ interface 注解标识符 注解类型的内容
    
    注解类型声明中的标识符指定了注解类型的名称。
    如果注解类型与它的任何封闭类或接口具有相同的简单名称,则编译时会出现错误。
    每个注解类型的直接父接口都是java.lang.annotation.Annotation。
    

    javap -c -v D:\Projects\rxjava-seed\target\classes\club\Counter.class

    Classfile /D:/Projects/rxjava-seed/target/classes/club/throwable/annotation/Counter.class
      Last modified 2018-10-6; size 487 bytes
      MD5 checksum 83cee23f426e5b51a096281068d8b555
      Compiled from "Counter.java"
    public interface club.throwable.annotation.Counter extends java.lang.annotation.Annotation
      minor version: 0
      major version: 52
      flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
    Constant pool:
       #1 = Class              #19            // club/throwable/annotation/Counter
       #2 = Class              #20            // java/lang/Object
       #3 = Class              #21            // java/lang/annotation/Annotation
       #4 = Utf8               count
       #5 = Utf8               ()I
       #6 = Utf8               AnnotationDefault
       #7 = Integer            0
       #8 = Utf8               SourceFile
       #9 = Utf8               Counter.java
      #10 = Utf8               RuntimeVisibleAnnotations
      #11 = Utf8               Ljava/lang/annotation/Retention;
      #12 = Utf8               value
      #13 = Utf8               Ljava/lang/annotation/RetentionPolicy;
      #14 = Utf8               RUNTIME
      #15 = Utf8               Ljava/lang/annotation/Documented;
      #16 = Utf8               Ljava/lang/annotation/Target;
      #17 = Utf8               Ljava/lang/annotation/ElementType;
      #18 = Utf8               TYPE
      #19 = Utf8               club/throwable/annotation/Counter
      #20 = Utf8               java/lang/Object
      #21 = Utf8               java/lang/annotation/Annotation
    {
      public abstract int count();
        descriptor: ()I
        flags: ACC_PUBLIC, ACC_ABSTRACT
        AnnotationDefault:
          default_value: I#7}
    SourceFile: "Counter.java"
    RuntimeVisibleAnnotations:
      0: #11(#12=e#13.#14)
      1: #15()
      2: #16(#12=[e#17.#18])
    

    既然注解最后转化为一个接口,注解中定义的注解成员属性会转化为抽象方法,那么最后这些注解成员属性怎么进行赋值的呢?答案就是:为注解对应的接口生成一个实现该接口的动态代理类。直接点说就是:Java通过动态代理的方式生成了一个实现了"注解对应接口"的实例,该代理类实例实现了"注解成员属性对应的方法",这个步骤类似于"注解成员属性"的赋值过程,这样子就可以在程序运行的时候通过反射获取到注解的成员属性(这里注解必须是运行时可见的,也就是使用了@Retention(RetentionPolicy.RUNTIME),另外需要理解JDK原生动态代理和反射相关内容)。

    枚举
    image.png

    javap -c -v D:\Projects\rxjava-seed\target\classes\club\enumeration\PhoneOsEnum.class

    枚举的声明格式是:{ClassModifier} enum Identifier [Superinterfaces] EnumBody,
    ClassModifier是修饰符,Identifier是枚举的名称可以类比为类名,枚举类型可以实现接口。
    枚举类型不能使用abstract或者final修饰,否则会产生编译错误。
    枚举类型的直接超类是java.lang.Enum。
    枚举类型除了枚举常量定义之外没有其他实例,也就是枚举类型不能实例化。
    枚举类型禁用反射操作进行实例化(这个特性就是Effetive Java中推荐使用枚举实现单例的原因)。
    

    JDK中枚举的底层实现就是使用了enum关键字声明的枚举类编译后最终会变成public final修饰同时实现了泛型接口java.lang.Enum并且指定泛型参数为自身的普通Java类,而成员属性和方法实现相关都是在编译完成后就已经成型的,枚举类型的成员变量都是通过静态代码块声明的。

    相关文章

      网友评论

          本文标题:java 注解枚举的底层实现

          本文链接:https://www.haomeiwen.com/subject/zyerbktx.html