注解详解

定义

注解也被称为元数据,它是一种代码级别的说明,可以声明在包、类、属性、方法、局部变量、方法参数等的前面,用来对这些元素进行说明和注释。注解可以用来标记生成文档,对代码进行分析,以及实现编译检查。

语法

在这里插入图片描述

  • 注解通过 @interface 关键字进行定义。
  • 没有注解元素的注解称为标记注解。
  • 元注解是用来注解其他注解的注解,Java中包含4种元注解:
    • @Target:用于标记该注解可以用于什么地方,ElementType参数的值包括:
      • CONSTRUCTOR:构造器的声明。
      • FIELD:域声明(包括enum实例)。
      • LOCAL_VARIABLE:局部变量声明。
      • METHOD:方法声明。
      • PACKAGE:包声明。
      • PARAMETER:参数声明。
      • TYPE:类、接口(包括注解类型)或enum声明。
    • @Retention:表示需要在什么级别保存该注解信息,RetentionPolicy参数的值包括:
      • SOURCE:注解将被编译器去掉。
      • CLASS:注解在class文件中可用,但会被vm丢弃。
      • RUNTIME:vm将在运行期也保留注解,可以通过反射机制读取注解的信息。
    • @Documented:将此注解包含在Javadoc中。
    • @Inherited:允许之类继承父类中的注解。
    • @Repeatable:允许注解重复使用,这是jdk1.8中引入的新注解,在之前的jdk版本中,同一个注解是不允许在同一个地方重复使用的。
  • 注解元素的定义非常类似于接口方法的定义,区别在于注解可以通过 default 关键字给元素指定默认值。
  • 注解元素可用的类型包括:
    • 所有基本类型(如 int、float、double等)。
    • String
    • Class
    • enum
    • Annotation
    • 以上类型的数组。
    • 使用其他类型编译器会报错,并且也不可以使用包装类型(如:Integer等)。
  • 元素默认值不能为null,可以使用空字符串或负数来表示元素不存在。

通过对注解语法的了解,我们发现注解的定义和接口的定义有太多的相似之处,那么他们之间有什么联系呢?为了一探究竟,我们一起观察下注解的字节码和接口的字节码有什么区别。
编写一个测试注解(DemoAnnotation.java):

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DemoAnnotation {

    public int id();

    public String name();

    public String desc() default "demo desc";
}

通过 javac 命令进行编译,生成class文件,然后再通过javap -c 命令对其反编译:
在这里插入图片描述
再编写一个测试接口(DemoInterface.java):

package annotation;

public interface DemoInterface {

    public int id();

    public String name();

    public String desc();
}

同样通过 javac 命令进行编译,生成class文件,然后再通过javap -c 命令对其反编译:
在这里插入图片描述
通过上面的结果发现,注解其实就是一个继承了Annotation类的接口。

JDK内置的注解

  • @Override:表示当前方法重写了父类的方法。
  • @Deprecated:如果使用了被该注解标记的元素会抛出警告,一般用来标记某些过期的类、属性或方法等。
  • @SuppressWarning:关闭不当的编译器警告信息。
  • @SafeVarargs:该注解是在JDK1.7中引入的,其作用是抑制编译器产生unchecked警告。在声明具有模糊类型的具有可变参数的方法时,编译器会报unchecked警告,如果程序员断言声明的方法不会对其varargs执行潜在的不安全操作,那么使用该注解编译器就不会再抛出unchecked警告了。
  • FunctionalInterface:该注解是在JDK1.8中引入的,通过该注解标记表明,该类型声明是按照Java语言规范定义的功能接口。

注解处理器

注解其实可以看成是一个特殊的注释,如果没有读取注解的工具,其功能并不会比注释的功能强多少。而我们平常之所以会使用注解,主要是为了搭配注解处理器来使用,这样做的好处是可以使我们的代码变的干净易读。需要用注解来标记处理的逻辑往往具备通用性,或者业务无关性,如果将这部分代码和业务代码糅合在一起,会使我们的代码变的冗余,不利于维护。

我们可以使用反射API来读取注解信息:

// Class类的isAnnotationPresent方法,用来判断该类是否被指定注解标记
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

//getAnnotation方法,用来获取指定Annotation对象
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)

//getAnnotations方法,用来获取所有Annotation对象
public Annotation[] getAnnotations()

Field、Method同样可以通过getAnnotation()、getAnnotations()方法来获取注解信息,获取到注解信息后就可以处理我们想要的逻辑了,这就是注解处理器的工作。

APT技术

待完善

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

成汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值