javaSE注解核心剖析

注解概念:

简单理解注解就是一种标记,常用于代替冗余的配置(XML,properties),又或者是编译器进行的一些检查如JDK自带的Override、Deprecated等。可以直白的来讲有注解和没有注解本质上不影响程序的运行。注解的作用在于「注解的处理程序」,注解处理程序通过捕获被注解标记的代码然后进行一些处理,这就是注解工作的方式。

注解本质:所谓的注解其实就是一个实现了Annotation的接口,而我们通过反射获取到的实际上是通过JDK动态代理生成的代理类,这个类实现了我们的注解接口

Java中进行定义注解:

Java中进行定义注解很简单,直接进行使用@interface即可完成注解的定义。

public @interface PrintMsg {
   
}

自定义注解的使用:

@PrintMsg
public class AnnotationTest {
   
    public static void main(String[] args) {
   
        System.out.println("annotation test OK!");
    }
}

我们发现写与不写这个注解的效果是相同的,这也印证了我们说的注解只是一种「标记」,有它没它并不影响程序的运行。

元注解:

元注解:对注解进行注解,也就是对注解进行标记,元注解的背后处理逻辑由apt
tool提供,对注解的行为做出一些限制,例如生命周期,作用范围等等。

@Retention:
用于描述注解的生命周期,表示注解在什么范围有效,它有三个取值,如下表所示:
在这里插入图片描述@Target:
用于描述注解作用的「对象类型」,这个就非常多了,如下表所示:
在这里插入图片描述@Documented:
将注解元素加入到javadoc之中。

@inherited:
如果被这个注解标记了,被标记的类、接口会继承父类、接口的上面的注解.

@Repeatable
表示该注解可以进行重复标记。

注解属性:
除了元注解之外,我们还能给注解添加属性,注解中的属性以无参方法的形式定义,方法名为属性名,返回值为成员变量的类型,还是以上述注解为例:
首先给这个注解加点细节,生命周期改为Runtime,使得运行期存在可以被我们获取。

@Retention(RetentionPolicy.RUNTIME)
public @interface PrintMsg {
   
    int count() default 1;
    String name() default "my name is PrintMsg";
}

@PrintMsg(count = 2020)
public class AnnotationTest {
   
    public static void main(String[] args) {
   
        //通过反射获取该注解
        PrintMsg annotation = AnnotationTest.class.getAnnotation(PrintMsg.class);
        System.out.println(annotation.count());
        System.out.println(annotation.name());
    }
}

输出如下:

2020
my name is PrintMs

注解分类:
按照注解的生命周期以及处理方式的不同,通常将注解分为「运行时注解」和「编译时注解」

1、运行时注解的本质是实现了Annotation接口的特殊接口,JDK在运行时为其创建代理类,注解方法的调用实际是通过AnnotationInvocationHandler的invoke方法,AnnotationInvocationHandler其中维护了一个Map,Map中存放的是方法名与返回值的映射,对注解中自定义方法的调用其实最后就是用方法名去查Map并且放回的一个过程
2、编译时注解通过注解处理器来支持,而注解处理器的实际工作过程由JDK在编译期提供支持,有兴趣可以看看javac的源码。

运行时注解详解:
之前我们说注解是一种标记,只是针对注解的作用而言,而Java语言层面注解到底是什么呢?以JSL中的一段话开头。

An annotation type declaration specifies a new annotation type, a special kind of interface type. To distinguish an annotation type declaration from a normal interface declaration, the keyword interface is preceded by an at-sign (@).

简单来说就是,注解只不过是在interface前面加了@符号的特殊接口,那么不妨以PrintMsg.class开始来看看,通过javap反编译的到信息如下:

public interface com.hustdj.jdkStudy.annotation.PrintMsg extends java.lang.annotation.Annotation
  minor version: 0
  major version: 52
  flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
  this_class: #1                          // com/hustdj/jdkStudy/annotation/PrintMsg
  super_class: #3                         // java/lang/Object
  interfaces: 1, fields: 0, methods: 2, attributes: 2
Constant pool:
   #1 = Class              #2             // com/hustdj/jdkStudy/annotation/PrintMsg
   #2 = Utf8               com/hustdj/jdkStudy/annotation/PrintMsg
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Class              #6             // java/lang/annotation/Annotation
   #6 = Utf8               java/lang/annotation/Annotation
   #7 = Utf8               count
   #8 = Utf8               ()I
   #9 = Utf8               AnnotationDefault
  #10 = Integer            1
  #11 = Utf8               name
  #12 = Utf8               ()Ljava/lang/String;
  #13 = Utf8               my name is PrintMsg
  #14 = Utf8               SourceFile
  #15 = Utf8               PrintMsg
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值