Annotation
通过使用Annotation,开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息,以便于检测错误,抑制警告等。Annotation不能运行,它只有成员变量,没有成员方法。
1、定义Annotation
定义一个新的Annotation类型,类似于定义一个接口
public @interface Test {
}
使用时,将Annotation另起一行,放在所有修饰符之前,如:
@Test
public class MyClass {
}
Annotation只有成员变量,其成员变量在定义中以无形参的方法形式来声明,其方法名定义了该成员变量的名字,返回值定义了该成员变量的类型。Annotation中的变量可以使用default关键字指定默认值。如:
public @interface MyTag {
String name() default "小明";
int age() default 18;
}
无默认值时,带成员变量的Annotation使用时,必须为成员变量指定值;有默认值时可以不指定。如:
//无默认值时
public class MyClass {
@MyTag(name = "小明", age = 30)
public void info() {
}
}
//有默认值时
public class MyClass {
@MyTag
public void info() {
}
}
Annotation可分为两类:
标记Annotation:没有成员变量,仅用自身提供信息。如:@Override
元数据Annotation:含成员变量
2、元注解
注解的注解,用来修饰Annotation。有四个:
@Retention
@Target
@Documented
@Inherited
1)、@Retention
@Retention用于指定Annotation可以保留多长时间。
@Retention包含一个名为“value”的成员变量,该value成员变量是RetentionPolicy枚举类型。使用@Retention时,必须为其value指定值。value成员变量的值只能是如下3个:
RetentionPolicy.SOURCE:Annotation只保留在源代码中,编译器编译时,直接丢弃这种Annotation。(此时注解用于注释)
RetentionPolicy.CLASS:编译器把Annotation记录在class文件中。当运行Java程序时,JVM中不再保留该Annotation。
RetentionPolicy.RUNTIME:编译器把Annotation记录在class文件中。当运行Java程序时,JVM会
保留该Annotation,程序可以通过反射获取该Annotation的信息。
例如:
//name=value形式
//@Retention(value=RetentionPolicy.RUNTIME)
//直接指定
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTag{
String name() default "小明";
}
2)、@Target
@Target指定Annotation用于修饰哪些程序元素。@Target也包含一个名为”value“的成员变量,该value成员变量类型为ElementType[ ],ElementType为枚举类型,值有如下几个:
ElementType.TYPE:能修饰类、接口或枚举类型
ElementType.FIELD:能修饰成员变量
ElementType.METHOD:能修饰方法
ElementType.PARAMETER:能修饰参数
ElementType.CONSTRUCTOR:能修饰构造器
ElementType.LOCAL_VARIABLE:能修饰局部变量
ElementType.ANNOTATION_TYPE:能修饰注解
ElementType.PACKAGE:能修饰包
例如:
//表示AnnTest可以修饰成员变量和方法
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface AnnTest {
String name() default "sunchp";
}
3)、@Documented
如果定义注解A时,使用了@Documented修饰定义,则在用javadoc命令生成API文档后,所有使用注解A修饰的程序元素,将会包含注解A的说明。
例如:
@Documented
public @interface Testable {
}
public class Test {
@Testable
public void info() {
}
}
4)、@Inherited
@Inherited指定Annotation具有继承性。
例如::
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyTag{
}
package com.demo2;
@MyTag
public class Base {
}
package com.demo2;
//SubClass只是继承了Base类
//并未直接使用@MyTag注解修饰
public class SubClass extends Base {
public static void main(String[] args) {
System.out.println(SubClass.class.isAnnotationPresent(MyTag.class));
}
}
示例中Base使用@MyTag修饰,SubClass继承Base,而且没有直接使用@MyTag修饰,但是因为MyTag定义时,使用了@Inherited修饰,具有了继承性,所以运行结果为true。
如果MyTag注解没有被@Inherited修饰,则运行结果为:false。
3、常用Annotation
JDK默认提供了如下几个基本Annotation:
1)、@Override
限定重写父类方法。对于子类中被@Override 修饰的方法,如果存在对应的被重写的父类方法,则正确;如果不存在,则报错。@Override 只能作用于方法,不能作用于其他程序元素。
2)、@Deprecated
用于表示某个程序元素(类、方法等)已过时。如果使用被@Deprecated修饰的类或方法等,编译器会发出警告。
3)、@SuppressWarning
抑制编译器警告。指示被@SuppressWarning修饰的程序元素(以及该程序元素中的所有子元素,例如类以及该类中的方法.....)取消显示指定的编译器警告。例如,常见的@SuppressWarning(value="unchecked")
4)、@SafeVarargs
@SafeVarargs是JDK 7 专门为抑制“堆污染”警告提供的。