Annotation
Java注解是在JDK5时引入的新特性。
我们可以利用注解帮我们在代码中添加一些其它的信息,如警告错误探测、警告信息提示、引入其它的方法等等。通过注解的方式,可以简化我们的代码,不需要编写很多冗余的代码。
我们定义了一个日志采集的注解,当我们需要对某个方法的运行时的传入参数、输出数据、异常信息等信息进行记录。我们只需要讲我们的注解放到该方法的上面即可,这样就不用我们在方法中编写日志记录的代码了。这样的代码看起来,清晰明了。也会提高编码效率。
注解
我们如何定义注解,我们需要使用注解给我们提供的“元注解”,来帮助我们定义注解。
元注解
元注解的作用就是负责注解其它注解的。它们被用来提供对其它注解类型进行解释说明。通俗讲,元注解就是帮助我们自定义注解时用到的方法,只不过是这种方法也被定义成了注解的形式。所以我们可以利用元注解来自定义注解。
- @Target (目标、指标)
- @Retention (保留、保持)
- @Documented (文件化、证明、记录在案)
- @Inherited (继承、继任)
@Target
描述注解的使用范围(可以用在什么地方)。注解可以被用到packages、types(类、接口、枚举、注解)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数、本地变量(循环变量、catch参数)。
ElementType:可配置的值
- CONSTRUCTOR: 表示该注解可以被用到构造器上。
- FIELD: 表示该注解可以被用到实体类的字段(成员变量、对象、属性等)上。
- LOCAL_VARIABLE: 表示该注解可以被用到局部变量上。
- METHOD: 表示该注解可以被用到方法上。
- PACKAGE: 表示该注解可以被用到包上。
- PARAMETER: 表示该注解可以被用到参数上。
- TYPE: 表示该注解可以被用到类(class)、接口(interface)、注解(@interface)、枚举(enum)上。
实例
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TableId {
// 使用范围为字段
}
上面的 @TableId 例子的使用范围为字段。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableName {
// 使用范围为类、接口(包括注解类型) 或enum
}
上面的 @TableName 例子的使用范围为类(class)、接口(interface)、注解(@interface)、枚举(enum)。
@Retention
描述注解的生命周期(表示在什么级别时保存该注解信息。这里的生命周期是指生命周期中的一段时间范围,在那个时间范围是有效的,这里的时间范围不是时钟的时间,是指程序中的某个期间,如,编译期间、解释期间等)。
- 某些注解仅出现在源代码中,在编译时被编译器丢弃。
- 某些注解被编译在class文件中。
- 编译在class文件中的注解可能会被虚拟机忽略。
- 某些注解在class被装载时将被读取。
RetentionPoicy 可配置的值
- SOURCE: 表示该注释的在源文件(源代码)中是有效的,在编译阶段被丢弃,这些注解在编译结束之后不再有任何意义。它们不会被写入到字节码中。
- CLASS: 表示该注解在class字节码文件中是有效的。当进行类加载的时候被丢弃(注解的默认使用方式)。
- RUNTIME: 始终不会被丢弃。运行期间也保留该注解,因此可以使用反射机制读取该注解的信息(自定义注解通常使用这种方式)。
实例
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableName {
//在运行时有效
}
在运行时有效
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Data {
// 在源文件(代码)中有效。
}
该注解时lombok的注解,会帮我们的实体类自动生成setter,getter 等方法,这样我们的源代码中就不用写那么多setter,getter等方法了,看着很清晰,但是在编译代码时,会自动帮我们把setter,getter等方法编译出来。
@Documented
描述注解的一个标记状态,表示是否需要将注解信息添加到java文档中。该元注解没有配置参数。需要将注解信息添加到文档中就把这个注解加上即可,反之不用加。
实例
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableName {
//需要将该注解信息添加到Java文档中
}
@Inherited
描述注解的一个标记状态,表示某个被标注的类型是被继承的。如果一个注解使用了该配置,这个注解又被用到了一个class上,那么该注解将会被用到该class的子类上,本类不会使用。
实例
@Inherited
public @interface TableName {
//该注解将被用在使用此注解的class的子类上
}
自定义注解
通过上面对于注解元注解的介绍,对注解有了一个初步的了解,下面我们通过自定义注解,来加深注解的认识,并去了解在自定义注解时有那些需要注意的地方。
- 使用@interface来声明一个注解。
- 在进行自定义注解时,自定义的注解会自动会继承java.lang.annotation.Annotation这个接口,由编译程序自动完成其它细节。
- 在自定义注解时,不能再去继承其它类或者接口。
- 参数成员只能使用public或者默认(default)这两个访问修饰符。
- 参数成员只能用基本数据类型(byte,short,char,int,long,float,double,boolean)和String、Enum、Class、annotation等类型,及这些类型的数组。