JDK1.5开始增加了Annotation功能,该功能可用于类、构造方法、成员变量、方法、参数等的声明中。该功能并不影响程序的运行,但是会对编译器警告等辅助工具产生影响。
1、定义Annotation类型
在定义Annotation类型时,也需要用到用来定义接口的interface关键字,但需要在interface关键字前加一个"@"符号,就是定义Annotation类型的关键字了。这个关键字的隐含意思是继承了java.lang.annotation.Annotation接口。例如下列代码定义了一个Annotation类型:
public @interface NoMemberAnnotation{
}
上述例子定义的Annotation类型未包含任何成员,这样的Annotation类型被称为marker annotation,下面示例中将定义一个带有一个成员的Annotation类型:
public @interface OneMemberAnnotation{
String value();
}
//String:成员类型
//value:成员名称
在为Annotation类型定义成员时,也可以为成员设置默认值,示例如下:
public @interface DefaultValueAnnotation{
String describe() default "<默认值>";
Class type() default void.class;
}
在定义Annotation类型时,还可以通过Annotation类型@Target来设置Annotation类型适用的程序元素种类。如果为设置@Target,则表示适用于所有程序元素。枚举类ElementType中的枚举常量用来设置@Target:
枚举常量 | 说明 |
---|---|
ANNOTATION_TYPE | 表示用于Annotation类型 |
TYPE | 表示用于类、接口和枚举,以及Annotation类型 |
CONSTRUCTOR | 表示用于构造方法 |
FIELD | 表示用于成员变量和枚举常量 |
METHOD | 表示用于方法 |
PARAMETER | 表示用于参数 |
LOCAL_VARIABLE | 表示用于局部变量 |
PACKAGE | 表示用于包 |
通过Annotation类型@Retention可以设置Annotation的有效范围。枚举类RetentionPolicy中的枚举常量用来设置@Retention,如果未设置,Annotation的有效范围为枚举常量CLASS表示的范围。
枚举常量 | 说明 |
---|---|
SOURCE | 表示不编译Annotation到类文件中,有效范围最小 |
CLASS | 表示编译Annotation到类文件中,但是在运行时不加载Annotation到JVM中 |
RUNTIME | 表示在运行时加载Annotation到JVM中,有效范围最大 |
2、访问Annotation信息
如果在定义Annotation类型时将@Rentention设置为RententionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息,如获取构造方法、字段和方法的Annotation信息。
类Constructor、Field和Method均继承了AccessibleObject类,在AccessibleObject中定义了3隔关于Annotation的方法,如下:
(1)isAnnotationPresent(Class<?extends Annotation>annotationClass):用来查看是否添加了指定类型的Annotation,如果则返回true,否则返回false
(2)getAnnotation(Class<T>annotationClass):用来获得指定类型的Annotation,如存在则返回相应的对象,否则返回null
(3)getAnnotations():用来获得所有的Annotation,返回一个Annotation数组
在类Constructor和Method中还定义了方法getParameterAnnotation方法,该方法用来获得为所有参数添加的Annotation,将以Annotation类型的二维数组返回,在数组中的顺序与声明的顺序相同,如果没有参数则返回一个长度为0的数组;如果存在未添加Annotation的参数,将用一个长度为0的嵌套数组占位。