Annotation 其实就是代码里的特殊标记,这些标记可以在编译、类加载或运行时被读取,并执行相应的处理。通过使用 Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。
Annotation 可以像修饰符一样被使用,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明, 这些信息被保存在 Annotation 的 “name=value” 对中。
Annotation 能被用来为程序元素(类、方法、成员变量等)设置元数据。
限定重写父类(或接口)的方法, 该注解只能用于方法。
interface Info{
void show();
}
class Season{
@Override
public void show() {
System.out.println("这是一个季节");
}
}
虽然不加Override也可以识别重写的方法。但加了注解之后,有以下两个好处:
便于调试
如果该方法不是父类的方法(比如写错了方法名的某个字母)则编译器会报错,便于调试。
一目了然
用于表示某个程序元素(类, 方法等)已过时。
当某类或方法已经有更好的方式替代,但为了兼容性,又不能直接淘汰,就可以使用这个注解,这样新的程序开发时就可以看到这样的改变(用IDE开发时可以看到提示,比如过时的代码会被横线划掉),从而尽量避免使用过时的代码,而使用其替代方案。在一定的时间之后,当所有程序基本上都使用了新的方式时,旧的代码可能被淘汰。
@Deprecated(since="9")
public Integer(int value) {
this.value = value;
}
抑制编译器警告。当有需要时,可以这样抑制一些编译器的警告,以满足程序员的“需求”,但使用时应知道自己在干什么。
@SuppressWarnings("unused")
public void printColl(@SuppressWarnings("rawtypes") Collection coll) {
@SuppressWarnings("rawtypes")
List list = new ArrayList();
for(Object object : coll) {
System.out.println(object);
}
}
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
public @interface MyAnnotation {
String name() default "hello";
}
没有成员定义的 Annotation 称为标记;包含成员变量的 Annotation 称为元数据 Annotation。
JDK 的元 Annotation 用于修饰其他 Annotation 定义。
JDK5.0提供了专门在注解上的注解类型。
几个基本注解的定义中就有元注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
/**
* Returns the version in which the annotated element became deprecated.
* The version string is in the same format and namespace as the value of
* the {@code @since} javadoc tag. The default value is the empty
* string.
*
* @return the version string
* @since 9
*/
String since() default "";
/**
* Indicates whether the annotated element is subject to removal in a
* future version. The default value is {@code false}.
*
* @return whether the element is subject to removal
* @since 9
*/
boolean forRemoval() default false;
}
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
/**
* The set of warnings that are to be suppressed by the compiler in the
* annotated element. Duplicate names are permitted. The second and
* successive occurrences of a name are ignored. The presence of
* unrecognized warning names is not an error: Compilers must
* ignore any warning names they do not recognize. They are, however,
* free to emit a warning if an annotation contains an unrecognized
* warning name.
*
* The string {@code "unchecked"} is used to suppress
* unchecked warnings. Compiler vendors should document the
* additional warning names they support in conjunction with this
* annotation type. They are encouraged to cooperate to ensure
* that the same names work across multiple compilers.
* @return the set of warnings to be suppressed
*/
String[] value();
}
用于指定该 Annotation 可以保留多长时间, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用 @Rentention 时必须为该 value 成员变量指定值。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
用于指定被修饰的 Annotation 能用于修饰哪些程序元素。包含一个名为 value 的成员变量。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE,
/**
* Module declaration.
*
* @since 9
*/
MODULE
}
用于指定被被修饰的 Annotation 类将被 javadoc 工具提取成文档。
定义为 Documented 的注解必须设置 Retention 值为 RUNTIME。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
被它修饰的 Annotation 将具有继承性。如果某个类使用了被 @Inherited 修饰的 Annotation,则其子类将自动具有该注解。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口,该接口代表程序中可以接受注解的程序元素。
程序可以调用 AnnotatedElement 对象的如下方法来访问 Annotation 信息。
Modifier and Type | Method and Description |
---|---|
|
getAnnotation(Class Returns this element’s annotation for the specified type if such an annotation is present, else null. |
Annotation[] |
getAnnotations() Returns all annotations present on this element. |
Annotation[] |
getDeclaredAnnotations() Returns all annotations that are directly present on this element. |
boolean |
isAnnotationPresent(Class extends Annotation> annotationClass) Returns true if an annotation for the specified type is present on this element, else false. |