注解相当于一种标记,在程序中加入注解就等于为程序打上了某种标记,以后,javac编译器、开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事,标记可以加在包、类、字段、方法、方法的参数以及局部变量上。
Java5常用有三种注解:
l Deprecated
用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
l Override
表示一个方法声明打算重写超类中的另一个方法声明。
l SuppressWarnings
指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。
注解有三个生命周期:
l Java源文件
l class文件
l 内存中的字节码
在注解中使用@Retention元注解来表示注解的生命周期,取值是一个枚举RetentionPolicy,分别有CLASS、RUNTIME、SOURCE
RetentionPolicy取值描述
值 | 描述 |
CLASS | 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。;及存放在class文件 |
RUNTIME | 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。及存放在内存中的字节码 |
SOURCE | 编译器要丢弃的注释。及存放在Java源文件 |
例子代码:
新建一个注解 @Retention(RetentionPolicy.RUNTIME) public @interface AnnotationTest { } 测试代码: @AnnotationTest public class Test { public static void main(String[] args) throws Exception{ if(Test.class.isAnnotationPresent (AnnotationTest.class)){ AnnotationTest annotation = (AnnotationTest)Test.class. getAnnotation(AnnotationTest.class); System.out.println(annotation); } } 如果RetentionPolicy取值为RUNTIME,就可以打印出结果,因为注解一直保持在运行期间 如果RetentionPolicy取值为SOURCE,不能打印出结果,因为注解只保存在Java文件中。 如果RetentionPolicy取值为Class,不能打印出结果,因为注解只保存在class文件中。 |
注解可以包、类、字段、方法、方法的参数以及局部变量上,那怎么去区分包、类?在注解中是使用@Target元注解来区分,取值是一个枚举ElementType,分别有CONSTRUCTOR、FIELD、METHOD等。
ElementType取值描述
取值 | 描述 |
ANNOTATION_TYPE | 注释类型声明 |
CONSTRUCTOR | 构造方法声明 |
FIELD | 字段声明(包括枚举常量) |
LOCAL_VARIABLE | 局部变量声明 |
METHOD | 方法声明 |
PACKAGE | 包声明 |
PARAMETER | 参数声明 |
TYPE | 类、接口(包括注释类型)或枚举声明 |
例子代码:
新建一个注解 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.TYPE}) public @interface AnnotationTest { } 如果ElementType取值为METHOD,注解只能标识方法 如果ElementType取值为TYPE,注解只能标识类、接口、枚举 多个值以逗号分开 |
注解还有一个强大的功能,那就是注解的属性。
那什么是注解的属性?
一个注解相当于一个学生证,如果你有一个学生证,代表你是一个学生,否则,就不是。如果还想区分出哪个学校的学生,这时候可以为学生证添加一个属性来进行区分。例如:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Student { String schoolName(); } 客户端测试代码: @Student (schoolName="清华") public class AnnotationTest { public static void main(String[] args) throws Exception{ if(AnnotationTest.class.isAnnotationPresent (Student.class)){ Student annotation = (Student)AnnotationTest.class. getAnnotation(Student.class); System.out.println(annotation.schoolName()); } } |
我们还可以为注解属性添加默认值,只需在属性后面添加default 值,例如
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Student { String schoolName() default "清华"; } 这样我们应用注解时,就可以不为schoolName属性赋值了 @Student public class AnnotationTest { ……………… } |
注解中有一个特殊的属性value,如果注解中有一个名称为value的属性,且你只想设置value属性(其他为默认),那么可以省略value=部门,例如:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Student { String schoolName() default "清华"; String value(); } @Student("XXX") public class AnnotationTest { ……………… } |