一、概述
关于注解,首先引入官方文档的一句话:Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。接下我将从注解的定义、元注解、注解属性、自定义注解、注解解析JDK 提供的注解这几个方面再次了解注解(Annotation)。
- 注解就像是一种标记;
- 可以作用在类的源码时期,编译时期和运行时期;
- 标记后的类,可以基于反射或字节码注入的形式对其实施一些操作;
- 注解是一种元编程的概念;
二、注解的语法
1、定义注解
日常开发中,我们使用 class、interface 比较多,而注解和它们一样,也算一种类的类型,使用的修饰符为 @interface
新建一个注解 NotNull,如下:
public @interface NotNull { }
接着我们可以使用 NotNull 注解作用在类、方法和参数上
@NotNull public class App { @NotNull public static void main(@NotNull String[] args) { } }
以上,我们只是了解的注解的写法,但是我们定义的注解中没有任何代码,这个注解暂时没有任何意义。那么,要如何使注解工作呢?我们下面来了解元注解。
2、元注解
元注解我们可以理解为注解的注解,它是用来修饰其他注解的,方便我们使用注解来实现我们想要的功能。
元注解分别有以下五种:
@Retention
- Retention英文意思有保留、保持的意思。在@Retention注解中使用枚举 RetentionPolicy 来表示注解保留时期,枚举的取值分别为:SOURCE、CLASS和RUNTIME,分别代表源码期、class字节码文件期和运行期。
- @Retention(RetentionPolicy.SOURCE):注解仅存在于源码中,当Java文件编译成class文件的时候,注解被遗弃;
- @Retention(RetentionPolicy.CLASS): 默认的保留策略,注解会在class字节码文件中存在,但运行时被遗弃;
- @Retention(RetentionPolicy.RUNTIME): 注解不仅会在class字节码文件中存在,在运行时可以通过反射获取到;
我们自定义的注解如果只存在于源码期或class字节码期就无法发挥作用,而在运行期能够获取到注解才是我们最终的目的,所以,自定义注解一般是使用@Retention(RetentionPolicy.RUNTIME),如下:
@Retention(RetentionPolicy.RUNTIME) public @interface NotNull { }
@Target
- @Target 英文意思是目标,用来描述修饰的对象范围,可以包括: packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数);
- @Target(ElementType.TYPE) :作用接口、类、枚举、注解;
- @Target(ElementType.FIELD) :作用属性字段、枚举的常量;
- @Target(ElementType.METHOD) :作用方法;
- @Target(ElementType.PARAMETER) :作用方法参数;
- @Target(ElementType.CONSTRUCTOR) :作用构造方法;
- @Target(ElementType.LOCAL_VARIABLE):作用局部变量;
- @Target(ElementType.ANNOTATION_TYPE):作用于注解(@Retention注解中就使用该属性);
- @Target(ElementType.PACKAGE): 作用于包;
- @Target(ElementType.TYPE_PARAMETER) :作用于类型泛型,即泛型方法、泛型类、泛型接口 (jdk1.8加入);
- @Target(ElementType.TYPE_USE) :类型使用,可以用于标注任意类型除了 class (jdk1.8加入);
比较常用的的是 ElementType.TYPE 类型,我们来看一下:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.PARAMETER}) public @interface NotNull { }
注解 NotNull 在定义时 Target 声明了只能作用于方法和方法参数,所以在使用时,作用于类时就报错了。
@Document
- Document:它的作用是标识注解写进 javadoc 文档;
@Inherited
- Inherited的英文意思是继承,这个继承和我们平时理解的继承大同小异,一个被 @Inherited 注解了的注解修饰了一个父类,如果他的子类没有被其他注解修饰,则它的子类也继承了父类的注解;
@Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.PARAMETER,ElementType.TYPE}) public @interface NotNull { }