Annotation是java中重要的特性,该技术在spring、Habinate等框架中大量使用。通过java自带的三种注释,来窥探注释的应用和原理,这样在后面使用这些框架的时候,可以迅速上手。
注释是什么?注释为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后某个时刻非常方便的使用这些数据。
为什么要用注释?注释实现了对元数据的支持,能够使开发人员在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息,并且这些信息可以通过编译器检查格式的正确性。通过使用注释,我们可以将这些元数据保存在java源代码中,并利用annotation API为自己的注解构造处理工具,同时,注释的优点还包括:更加干净易读的代码以及编译期类型检查等。
一、注释的使用
①注释可以用来修饰类、属性、方法,而且Annotation不影响程序运行,无论是否使用Annotation代码都可以正常执行。java.lang.annotation.Annotation是Annotation的接口,只要是Annotation都必须要实现此接口。接口的定义如下:
public interface Annotation{
public Class extends Annotation> annotationType();
public boolean equals(Object obj);
public int hashCode();
String toString();
}
②java内建的Annotation。在jdk1.5之后,系统已经建立了3个内建的Annotation类型,用户直接使用即可,他们分别是:
- Override---覆写的Annotation;
- Deprecated----不赞成使用的Annotation
- SuppressWarnings----压制安全警告的annotation.
以上3个Annotation都是前面提到的Annotation接口的子类。在java中都有各自的定义,如下:
其中:①@Override主要在方法覆写时使用,用于保证方法覆写时使用,用于保证方法覆写的正确性。如果方法没有达到覆写的要求,则在类编译时,就会哭抛出异常;并且该注释只能用于检测方法的覆写上,其他元素,如类、属性等不能使用。②@Deprecated的主要功能是用来声明一个不建议使用的方法。如果在程序中使用了此方法,则在编译时将出现警告信息。该注释除了方法上声明外,在类中也可以进行声明,表示该类不建议使用。③@SuppressWarnings主要功能是用来压制警告。并且在使用的过程中,可以设置压制警告的类别,使用时,以字符串数组的形式进行声明。该注释支持的关键字如下:
之前介绍了3中java中定义的Annotation,只要通过固定的格式调用即可。但是想要充分理解Annotation的作用必须结合枚举、反射等机制才可以。所以,下面介绍如何定义Annotation。
1、Annotation的定义格式:
[public] @interface Annotation名称{
数据类型 变量名称();
}
注意:在定义Annotation必须使用@interface的方式进行定义。在定义Annotation时也可以定义各种变量,但是变量定义之后必须使用“()”。
提示:使用@interface就相当于继承了Annotation接口。在程序中使用了@interface声明Annotation,那么此Annotation实际上就相当于继承了java.lang.annotation.Annotation接口。
2、自定义一个Annotation,如下:
注意:通过上面的例子我们可知,如果注释中定义的属性没有设置默认值,则在使用注释的时候,需要给属性设置值;如果设置了默认值,则在使用时,可以不用指定值;如果想要为一个属性设置多个内容,则必须将一个属性定义成一个数组。
4、Retention和RetentionPolicy
在Annotation中,可以使用Retention定义一个Annotation的保存范围。此Annotation的定义如下:
在以上的Retention定义中存在一个RetentionPolicy的变量,此变量用于指定Annotation的保存范围,RetentionPolicy包含3个范围,如下:
并且我们可以看一下java的3个内建Annotation的定义:
①ovrride定义采用的是@Retention(value=SOURCE),只能在源文件中出现;
②Deprecated定义采用的是@Retention(value=RUNTIME),可以在执行时出现。
③SuppressWarnings定义采用的是@Retention(value=SOURCE),只能在源文件中出现。
三、通过反射取得Annotation
如果要让一个Annotation起作用,则必须结合反射机制。在Class类中存在一下几个与Annotation操作有关的方法,如下:
注意:①要取得toString()方法上的全部注释,则必须首先通过反射找到toString()方法。
②虽然我们在定义一个方法时,会使用很多Annotation注释,但是最后真正得到的只能是@Retention(value=RUNTIME)的。
③通过程序我们可以取得一个元素所声明的全部RUNTIME的Annotation,但是如果只需要某个指定的Annotation,则在取得之前就必须进行明确的判断,使用isAnnotationPresent()方法进行判断。
四、@Target注释
如果一个Annotation没有明确的指明定义的位置,则可以在任意的位置使用,而如果希望一个自定义的Annotation只能在指定的位置上出现,则必须使用@Target注释。在Target的注释中存在一个ElementType[]枚举类型的变量,这个变量主要指定Annotation的使用限制,如下:
通过使用@target({ElementType.TYPE,ElementType.METHOD}),限定Annotation的出现位置,如果没有出现在指定的位置,则在编译时抛出异常。
四、还常用的一些注释
1、@Documented注释。任何一个自定义的Annotation实际上都是通过@Documented进行注释的,在生成javadoc时通过@Documented将一些文档的说明信息写入。
2、Inherited注释。用于注释一个父类的注释是否可以被子类继承,如果一个Annotation需要被其子类继承,则在声明时直接使用@Inherited注释即可。如果在声明Annotation时没有加上@Inherited注释,则此Annotation是无法被继承的。