也称为元数据,为在代码中添加信息提供一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。将元数据和源代码二建结合起来,而不是保存在外部文档中。能够提供更加干净易读的代码以及编译期类型检查。
注解的定义如下图所示,看起来像接口的方法,唯一的区别是可以指定默认值。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface useCase {
public int id();
public String description() default "no description";
}
注解使用时为名-值对的形式,例如下图中调用useCase的注解,我们可以很方便地看出下面每一个方法对应的功能描述,从而避免了另外书写代码文档。
public class PasswordUtils {
@useCase(id=47,description = "password must contain at least one numeric")
public boolean validatePassword(String password){
return (password.matches("\\w*\\d\\w*"));
}
@useCase(id=48)
public String encryptPassword(String password){
return new StringBuilder(password).reverse().toString();
}
@useCase(id=49, description = "New passwords can't equal previously used ones")
public boolean checkForNewPassword(List<String> prevPasswords, String password){
return !prevPasswords.contains(password);
}
}
如果单单是上文中展示的注解的话,我们通过普通的注释就可以实现这种解释代码的功能。所以关键的优点就在于,可以结合反射机制使用注解处理器帮助程序员解析带有注解的java源代码。
什么意思呢,通俗一点讲就是。如果一个项目有1,2,3,4,5共五个功能点,而程序员实现了1,2,3共3个功能点,并在其上面添加注解。如果使用普通注释的话,主管在检查代码时,需要查阅源代码,一个一个看功能点是否实现,非常费时。那如果我们使用注解,我们可以结合反射机制,通过代码直接快速检查功能点是否存在。
如下面的代码所示,假设我们在最初的设计文档中设计了47,48,49,50一共5个函数功能点,那么通过获取所有的annotation列表,直接排查就可以得到我们还有哪个功能点暂未实现。
代码中,第3-9行将找到的useCase从列表中依次去除,最后10-12行将列表中还存在的useCase输出,表明是没有找到的case。
cl.getDeclaredMethods()获得类中声明的所有方法,m.getAnnotation获取方法中对应的注解。
public class UseCaseTracker {
public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
for(Method m: cl.getDeclaredMethods()){
useCase uc = m.getAnnotation(useCase.class);
if(uc != null){
System.out.println("Found Use Case: " + uc.id() + " " + uc.description());
useCases.remove(new Integer(uc.id()));
}
}
for(int i : useCases){
System.out.println("Waning: Missing use case-"+i);
}
}
public static void main(String[] args){
List<Integer> useCases = new ArrayList<Integer>();
Collections.addAll(useCases,47,48,49,50);
trackUseCases(useCases,PasswordUtils.class);
}
}
注解内的元素包括:
注解的默认值不能有不确定的值,要么是默认值要么是注解时提供的值。不能以null作为其值,如果想要表示某个元素不存在,可以自定义一些特殊的值。
单元测试是注解的一个重要功能,最常用的为@Test注解。@Test标记测试方法,不带参数,返回值为boolean类型来表示测试成功与否。
优点
一个简单的单元测试如下:
import net.mindview.atunit.Test;
public int methodOne(){
return 1;
}
@Test
boolean testOne(){
return methodOne()==1;
}