注解,也被称为元数据,为我们在代码中添加信息提供了一种形式化的方法,使我们在稍后的某个时刻非常方便的使用这些数据。
Java SE内置了三种定义在java.lang中的注解:
@Override,表示当前方法定义将覆盖超类中的方法。
@Deprecated,如果程序员使用了注解为它的元素,那么编译器发出警告信息。
@SuppressWarning,关闭不当的编译器警告信息。
Java另外还提供了4种元注解(meta-annotation),负责新注解的创建:
@Target 表示该注解可以用于什么地方。
可能的ElementType包括:CONSTRUCTOR
(构造器声明),FIELD
(域声明包括enum实例),LOCAL_VARIABLE
(局部变量声明),METHOD
(方法声明),PACKAGE
(包声明),PARAMETER
(参数声明),TYPE
(类,接口或enum声明)。
@Retention 表示需要在什么级别保存该注解信息。
可选的RententionPolicy参数包括:SOURCE
(注解将被编译器丢弃),CLASS
(注解在class文件中可用,JVM丢弃),RUNTIME
(CM在运行期也保留,可以通过反射读取注解信息)。
@Documented 将该注解包含在Javadoc中。
@Inherited 允许子类继承父类中的注解。
下面是一个简单的注解,用于跟踪一个项目中的用例。RD可以在实现的测试用例上添加该注解@UseCase
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
public int id();
public String description() default "Use Case";
}
如下程序实现了一个简单的注解处理器,使用反射来查找@UseCase
标记。该程序用到了两个反射方法:getDeclaredMethods()
和getAnnotaion()
,它们都属于AnnotatedElement
接口(Class,Method和Field等类都实现了该接口)。
import java.lang.reflect.Method;
public class UseCaseTracker {
public static void track(Class<?> cl){
for (Method m : cl.getDeclaredMethods()) {
UseCase uc = m.getAnnotation(UseCase.class);
if(uc!=null) {
System.out.println("Found useCase:" + uc.id() + " " + uc.description());
}
}
}
public static void main(String[] args) {
UseCaseTracker.track(PasswordUtilTest.class);
}
}
import org.junit.Assert;
import org.junit.Test;
public class PasswordUtilTest {
@Test
@UseCase(id=5,description="密码校验,密码至少包含1个数字")
public void testPassword() {
String password = "aab123";
Assert.assertTrue(PassswordUtils.validate(password));
}
@Test
@UseCase(id=10,description="用于统计用例个数")
public void testTrack() {
UseCaseTracker.track(PasswordUtilTest.class);
}
}