注解为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后的某个时刻非常方便地使用这些数据。
注解使得我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息。注解可以用来生成描述符文件,甚至或是新的类定义,并且有助于减轻编写“样板”代码的负担。
@Target :表示注解可以用于什么地方。可能的ElementType参数包括:
CONSTRUCTOR:构造器声明
FIELD: 域声明
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE: 包声明
PARAMETER: 参数声明
TYPE:类,接口(包括注解类型)或enum声明
@Retention 表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数有:
SOURCE: 注解只保留在源文件,当java文件编译成class文件的时候,注解被遗弃
CLASS:注解被保留到class文件,但当jvm加载class文件时候被遗弃
RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。
这3个生命周期分别对应于:java源文件(.java文件)--->.class文件--->内存中的字节码
那怎么来选择合适的注解生命周期呢
首先要明确生命周期长度 SOURCE< CLASS < RUNTIME
一般如果需要在运行时去动态获取注解信息,那只能用RUNTIME注解,比如@Deprecated使用RUNTIME注解。
如果要在编译时进行一些预处理操作,比如生成一些辅助代码(ButterKnife)就用CLASS 注解。
如果只做一些检查性操作 比如@Override 和@ SuppressWarning,使用Source注解
代码示例:
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 "no description";
}
import java.util.*;
public class PasswordUtils {
@UseCase(id=47,description = "Password must contain at least one number")
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> prePasswords,String password){
return !prePasswords.contains(password);
}
}
import java.lang.reflect.Method;
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<>();
Collections.addAll(useCases,47 ,48 ,49 ,50 );
trackUseCases(useCases,PasswordUtils.class);
}
}
运行结果:
image.png
网友评论