JDK注解详解

一、什么是注解

  • 注解也叫元数据,例如我们常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解。
    (一)注解的作用
  • 不是程序本身,可以对程序作出解释
  • 可以被其他程序(比如:编译器等读取)
    (二)注解的格式
    @注解名
    (三)使用范围
    注解可以在package、class、method、field等上面,相当于为他们加载了额外的属性信息,我们可以通过反射机制变成实现对这些元数据的访问
    二、java中的内置注解
    (一)@Override
    该注解只适用于定义在方法之上,用于表示该方法重写了父类的同名方法
    (二)@Deprecate
    此注解可以用于修饰方法,属性,表示不鼓励、不赞成程序员使用这样的元素,通常是因为它很危险或者存在有更好的元素可以选择
    (三)SuppressWarnings
    用于抑制编译时的警告信息,和前两个注解不同,该注解需要添加一个参数才可以正确的使用
    三、元注解
  • 元注解即注解的注解,就是对注解的说明解释。Java中定义了4个标准的meta-annotation类型,用于提供对其他annotation类型作说明
  • 这些类型和它们所支持的类在java.lang下的annotation包中可以找到
  1. @Target:用于描述注解的使用范围


  2. @Retention:表示需要在上面级别保存该注解信息,用于描述注解的生命周期
    SOURCE(源码期)<CLASS(编译期)<RUNTIME(运行期)

  3. @Document:说明该注解将被包含在javadoc中

  4. @Inherited:说明子类可以继承父类中的该注解
    四、自定义注解
    使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口


自定义注解中可根据实际需要定义参数,格式如下:
数据类型 参数名称() ;

注意:

  • 参数的名称后面必须加(),这是固定格式

  • 参数的类型只可以是Class、enum、String

  • 可以通过default来申明参数的默认值,否则就需要在使用的时候进行赋值,否则会报错



    当设置了默认值后,编译不再报错


  • 注解元素必须要有值,我们定义元素时,通常使用空字符串,0作为默认值

  • 如果只有一个参数成员,一般参数名为value(建议)



    使用value的话,可以不用注明参数的key


五、注解的内在原理

  • 从java源码到class字节码是由编译器完成的,编译器会对java源码进行解析并生成class文件,而注解也是在编译时由编译器进行处理,编译器会对注解符号处理并附加到class结构中,根据jvm规范,class文件结构是严格有序的格式,唯一可以附加信息到class结构中的方式就是保存到class结构的attributes属性中。我们知道对于类、字段、方法,在class结构中都有自己特定的表结构,而且各自都有自己的属性,而对于注解,作用的范围也可以不同,可以作用在类上,也可以作用在字段或方法上,这时编译器会对应将注解信息存放到类、字段、方法自己的属性上。
  • 在我们的AnnotationTest类被编译后,在对应的AnnotationTest.class文件中会包含一个RuntimeVisibleAnnotations属性,由于这个注解是作用在类上,所以此属性被添加到类的属性集上。即Test注解的键值对value=test会被记录起来。而当JVM加载AnnotationTest.class文件字节码时,就会将RuntimeVisibleAnnotations属性值保存到AnnotationTest的Class对象中,于是就可以通过AnnotationTest.class.getAnnotation(Test.class)获取到Test注解对象,进而再通过Test注解对象获取到Test里面的属性值。
  • 这里可能会有疑问,Test注解对象是什么?其实注解被编译后的本质就是一个继承Annotation接口的接口,所以@Test其实就是“public interface Test extends Annotation”,当我们通过AnnotationTest.class.getAnnotation(Test.class)调用时,JDK会通过动态代理生成一个实现了Test接口的对象,并把将RuntimeVisibleAnnotations属性值设置进此对象中,此对象即为Test注解对象,通过它的value()方法就可以获取到注解值。
posted @ 2020-07-12 18:21  moutory  阅读(26)  评论(0编辑  收藏  举报  来源