在java SE5中,引入了Annotation的概念。引入Annotation,我们可以把一些metadata信息也放在源码文件里面,而不用放在另外一个文件。例如在Spring中,我们可以使用annotation来实现很多的功能。用起来也是非常的方便。特别是我们在写一些框架的时候,如果能自己定义一些Annotation,可以让我们的框架变得更加的好用。
- Annotation的简单语法
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
public int id();
public String description() default "no description";
}
这里我们可以看到,其他Annotation的定义和interface的定义十分的相似,只是多了一个@.在上面定义的过程中,我们发现我们使用了两个Annotation。一个是Target,一个是Retention。Target的作用是表明,我们这个定义的UseCase Annotation是用在哪里的。这里我们创建的UseCase是用来修改Method的。ElementType还有其他类型,可以参考
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/annotation/Retention.html。Retention是用来表用,我们创建的Annotation是在哪里生效的。我们定义的Annotation是用来在运行时候用的,所以应该定义为RUNTIME。RetentionPolicy还有其他类型,可以参考
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/annotation/Retention.html。
- Annotation的使用
import java.util.*;
public class PasswordUtils {
@UseCase(id = 47 , description = "Passwords must contain at least one numeric")
public boolean validatePassword(String password) {
return (password.matches("\\w*\\d\\w*"));
}
@UseCase(id = 48, description = null)
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>previousPasswords , String password) {
return !previousPasswords.contains(password);
}
}
我们使用上面定义的Annotation,来修饰PasswordUtils中的类。在这里我们需要注意的是,UseCase中,有些值有有默认值的,我们可以不给他赋值,如果没有默认值的话,是一定需要赋值的。
还有另外一点需要注意的,非primitive类型的数据,不能赋值为null.*(其实primitive类型的本来就不能赋值为null)
- 处理Annotation
在上面,我们在PasswordUtils中使用了我们自己定义的Annotation。但是我们仅仅把Annotation加进去还是远远不够的。Java中的一个默认的Annotation,如Override,Java中有专门的程序来处理这些Annotation。所以对于我们自己定义的Annotation,我们也需要自己定义程序来处理这些Annotation。
import java.lang.reflect.*;
import java.util.*;
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("Warning: 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);
}
}
上面的程序中,我们使用到了Java中的反射的一些内容。