• java元注解


    java元注解

    本文涉及以下这些内容,如果不清楚的话,可以看一下,相信会对你有些许帮助。:
    1)使用IntelliJ IDEA 2018查看字节码
    2)使用IntelliJ IDEA 2018生成帮助文档

    本文主要针对于java8,java8定义了6个标准元注解:@Target,@Retention,@Documented,@Inherited,@Repeatable和@Native。

    1.@Target注解。
    @Target注解的作用是:描述注解的使用范围(即被修饰的注解可以用在什么地方)。@Target注解用来说明那些被他注解的注解类可修饰的对象范围。

    @Target注解源码:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Target {
       
        ElementType[] value();
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    @Target注解的枚举参数:

    public enum ElementType {
    
      	//类,接口,枚举类
        TYPE, 
    
      	//成员变量,枚举常量
        FIELD, 
    
    	//方法
        METHOD,
    
    	//形式参数
        PARAMETER,
    
     	//构造方法
        CONSTRUCTOR,
    
    	//局部变量
        LOCAL_VARIABLE,
    
        //注解
        ANNOTATION_TYPE,
    
        //包
        PACKAGE,
    
        //类型参数
        TYPE_PARAMETER,
    
        //类型使用
        TYPE_USE
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2.@Retention注解。
    @Retention注解的作用是:描述注解保留的时间范围(即:被描述的注解在它所修饰的类中可以被保留到何时)。@Retention注解用来限定那些被他所注解的注解类在注解到其他类上以后,可被保留到何时。

    @Retention注解源码:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Retention {
       
        RetentionPolicy value();
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    @Retention注解的枚举参数:

    public enum RetentionPolicy {
       
       	//源文件保留
        SOURCE,
    
      	//编译期保留,默认值
        CLASS,
    
      	//运行期保留,可通过反射去获取注解信息
        RUNTIME
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    下面我们举个例子:

    注解:

    @Retention(RetentionPolicy.SOURCE)
    public @interface SourcePolicy {
    }
    
    • 1
    • 2
    • 3

    注解:

    @Retention(RetentionPolicy.CLASS)
    public @interface ClassPolicy {
    }
    
    • 1
    • 2
    • 3

    注解:

    @Retention(RetentionPolicy.RUNTIME)
    public @interface RuntimePolicy {
    }
    
    • 1
    • 2
    • 3

    测试类:

    public class RetentionTest {
    
        @SourcePolicy
        public void sourcePolicy(){
    
        }
    
        @ClassPolicy
        public void classPolicy(){
    
        }
    
        @RuntimePolicy
        public void runtimePolicy(){
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    RetentionPolicy 类的字节码文件中三个方法的部分:

      public void sourcePolicy();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=0, locals=1, args_size=1
             0: return
          LineNumberTable:
            line 8: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       1     0  this   Lannotation/RetentionTest;
    
      public void classPolicy();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=0, locals=1, args_size=1
             0: return
          LineNumberTable:
            line 13: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       1     0  this   Lannotation/RetentionTest;
        RuntimeInvisibleAnnotations:
          0: #14()
    
      public void runtimePolicy();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=0, locals=1, args_size=1
             0: return
          LineNumberTable:
            line 18: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       1     0  this   Lannotation/RetentionTest;
        RuntimeVisibleAnnotations:
          0: #17()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    根据上面方法的字节码我们可以看出:
    1)编译器没有记录sourcePolicy方法的注解信息。
    2)编译器使用了RuntimeInvisibleAnnotations属性记录classPolicy方法的注解信息,使用RuntimeVisibleAnnotations属性记录runtimePolicy方法的注解信息。

    3.Documented注解。
    Documented注解的作用是:描述在使用javadoc工具为类生成帮助文档时是否要保留其注解信息。

    Documented注解源码:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Documented {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    下面我们举个例子:

    注解:

    @Documented
    @Target({ElementType.TYPE,ElementType.METHOD})
    public @interface MyDocumentedAnnotation {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    测试类:

    @MyDocumentedAnnotation
    public class MyDocumentedTest {
    
        @MyDocumentedAnnotation
        @Override
        public String toString(){
            return this.toString();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    查看生成的帮助文档:

    类上的注解
    在这里插入图片描述

    接下来把@Documented注解去掉,重新生成帮助文档:
    在这里插入图片描述

    在这里插入图片描述

    由此我们可以看出@Documented注解的作用。

    4.Inherited注解。
    Inherited注解的作用是:使被他修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解。)

    下面我们举个例子:

    注解:

    @Inherited
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyInheritedAnnotation {
    
        public String name() default "pengjunlee";
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    父类:

    @MyInheritedAnnotation(name = "parent")
    public class Parent {
    }
    
    • 1
    • 2
    • 3

    子类:

    public class Child extends Parent {
    
        public static void main(String[] args) {
            Class<Child> child = Child.class;
            MyInheritedAnnotation annotation = child.getAnnotation(MyInheritedAnnotation.class);
            System.out.println(annotation.name());
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    输出:
    parent

    5.@Repeatable注解。
    @Repeatable注解的作用是:用于声明标记的注解为可重复类型注解,可以在同一个地方多次使用。

    @Repeatable 注解源码:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Repeatable {
        
        Class<? extends Annotation> value();
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    下面我们举个例子:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyRepeatableAnnotation {
    
        RepeatableAnnotationTest[] value();
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Repeatable(MyRepeatableAnnotation.class)
    public @interface RepeatableAnnotationTest {
    
        String key();
    
        String value();
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    @RepeatableAnnotationTest(key = "aa",value = "11")
    @RepeatableAnnotationTest(key = "bb",value = "22")
    public class RepeatableTest {
    
        public static void main(String[] args) {
            RepeatableAnnotationTest[] annotation = RepeatableTest.class.getAnnotation(MyRepeatableAnnotation.class).value();
            for (RepeatableAnnotationTest a : annotation) {
                System.out.println(a);
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出:
    @annotation.RepeatableAnnotationTest(key=aa, value=11)
    @annotation.RepeatableAnnotationTest(key=bb, value=22)

    6.@Native注解。
    @Native注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用。对于@Native注解不常使用,了解即可。

  • 相关阅读:
    前端周刊第十三期
    基于经验论述:实现k-NN算法
    【元胞自动机】元胞自动机晶体生长【含Matlab源码 232期】
    Python-数据爬取(爬虫)
    某网书籍信息爬虫
    R语言使用epiDisplay包的dotplot函数通过点图的形式可视化不同区间数据点的频率、使用pch参数自定义指定点图数据点的形状
    【Python基础】if __name__ == ‘__main__‘:和assert函数
    OpenCV12-图像卷积
    Google出品的NotebookLM 人工智能笔记本,一款基于RAG的personalized AI产品
    【leetcode 1】LinkList and Queue and Stack
  • 原文地址:https://blog.csdn.net/zh123456_789/article/details/115186313