JDK1.5开始增加了Annotation功能,该功能可用于类、构造方法、成员变量、方法、参数等的声明中。该功能不影响程序运行,但是会对编译器警告等辅助工具产生影响。
一、定义一个Annotation
public @interface UserName{}
使用@interface关键字定义一个注解
二、添加成员
public @interface UserName{ String value(); }
成员类型支持:String\class\primitive\enumerated\annotation,以及所列类型的数组;
三、添加默认值
public @interface UserName{ String value() default "default value"; }
四、指定可注解的类型
@Target(ElementType.Method) public @interface UserName{}
适用于注解在方法上,例如:
Class Car{ @UserName(value = "laye") public void drive(){} }
ElementType的种类有:
- ANNOTATION_TYPE:表示用于Annotation类型;
- TYPE:表示用于类、接口、以及Annotation和枚举类型;
- CONSTRUCTOR:表示用于构造方法;
- FIELD:表示用于成员变量和枚举常量;
- METHOD:表示用于方法;
- PARAMETER:表示用于参数;
- LOCAL_VARIABLE:表示用于局部变量;
- PACKAGE:表示用于包;
五、指定注解的有效范围
@Retention(RetentionPolicy.RUNTIME) public @interface UserName{}
表示在运行时有效,RetentionPolicy可选类型如下:
- SOURCE:表示不编译到类文件中;
- CLASS:表示编译到类文件,但运行时不加载;
- 表示在运行时加载;
六、访问注解
java.lang.reflect包下有一个类:AccesibleObject,它时Method\Field\Constructor的父类,同时它又实现了AnnotatedElement接口。因此,Method\Field\Constructor包含了访问注解的接口方法;
具体例子如下:
@Target(ElementType.FIELD) // 注解类型为变量 @Retention(RetentionPolicy.RUNTIME) // 有效范围为运行时 public @inteface UserName{ // 声明注解 String value() default "no body"; // 添加成员 } class Car{ @UserName(value = "lay") // 注解在变量上 public String owner; // 默认值 public static void main(String[] args) throws Exception{ Class c = Car.class; // 获取类类型 Field field = c.getField("owner"); // 获取对应变量 UserName userName = (UserName)field.getAnnotation(UserName.class); // 获取注解 System.out.println(userName.value()); // 获取注解的成员变量 Car car = new Car(); // 获取实例 field.set(car, userName.value()); // 设置实例的owner变量的值 } }
以上是一个访问field的示例,method和constructor等类同这样的写法;
常用方法:
- isAnnotationPresent(Class class):是否添加了指定类型的注解;
- getAnnotation(Class class): 获取指定类型的注解;
- getAnnotations(): 获取所有类型的注解;
- getParameterAnnotations(): 获取所有参数的注解;