Java Annotation使用大全
四、如何自定义Annotation?
1.详解annotation与接口的异同:
因为annotation类型是一个非凡的接口,所以两者之间存在着某些差异:
A.Annotation类型使用关键字@interface而不是interface。
这个关键字声明隐含了一个信息:它是继承了java.lang.annotation.Annotation接口,并非声明了一个interface。
B.Annotation类型、方法定义是独特的、受限制的。
Annotation 类型的方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型。而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用 default和一个默认数值来声明成员的默认值,null不能作为成员默认值,这与我们在非annotation类型中定义方法有很大不同。
Annotation类型和它的方法不能使用annotation类型的参数、成员不能是generic。只有返回值类型是Class的方法可以在annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。
C.Annotation类型又与接口有着近似之处。
它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。
2.实例:
下面,我们将看到如何定义annotation类型的example。它展示了annotation类型声明以及@interface与interface之间的不同:
清单10:
package com.davidflanagan.annotations;
import java.lang.annotation.*;
/**
* 使用annotation来描述那些被标注的成员是不稳定的,需要更改
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Unstable {}
下面的另一个example只定义了一个成员。并通过将这个成员命名为value,使我们可以方便的使用这种annotation的快捷声明方式:
清单11:
/**
* 使用Author这个annotation定义在程序中指出代码的作者
*/
public @interface Author {
/** 返回作者名 */
String value();
}
以下的example更加复杂。Reviews annotation类型只有一个成员,但是这个成员的类型是复杂的:由Review annotation组成的数组。Review annotation类型有3个成员:枚举类型成员grade、表示Review名称的字符串类型成员Reviewer、具有默认值的字符串类型成员 Comment。
清单12:
import java.lang.annotation.*;
/**
* Reviews annotation类型只有一个成员,
* 但是这个成员的类型是复杂的:由Review annotation组成的数组
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Reviews {
Review[] value();
}
/**
* Review annotation类型有3个成员:
* 枚举类型成员grade、
* 表示Review名称的字符串类型成员Reviewer、
* 具有默认值的字符串类型成员Comment。
*/
public @interface Review {
// 内嵌的枚举类型
public static enum Grade { EXCELLENT, SATISFACTORY, UNSATISFACTORY };
// 下面的方法定义了annotation的成员
Grade grade();
String reviewer();
String comment() default "";
}
最后,我们来定义一个annotation方法用于罗列出类运行中所有的unchecked异常(上文已经提到这种情况不一定是错误)。这个 annotation类型将一个数组作为了唯一的成员。数组中的每个元素都是异常类。为了加强对未检查的异常(此类异常都是在运行时抛出)进行报告,我们可以在代码中对异常的类型进行限制:
清单13:
public @interface UncheckedExceptions {
Class<? extends RuntimeException>[] value();
}