学习资料:
- Java编程思想 ——第20章
- 公共技术点之 Java 注解 Annotation
注解(Annotation)也被称为元数据,提供一种在代码中添加信息的形式化方法,在之后某个时刻可以方便地使用这些数据
元数据是描述数据的数据
注解是在Java SE5
中添加,可以完整地描述程序所需要而Java
代码无法来表达的信息。注解仅仅是元数据,与逻辑代码没有任何关系
1.基本语法 <p>
没有元素的注解称为标记注解
Java
中有4种元注解
元注解的作用就是负责注解其他注解 :(
元注解 | 作用 |
---|---|
@Target | 表示该注解可以用在什么地方 ElementType包括: CONSTRUCTOR –> 构造器的声明 FIELD –> 域声明 LOCAL_VARLABLE –> 局部变量声明 METHOD –> 方法声明 PACKGE –> 包声明 PARAMETER –> 参数声明 |
@Retention | 表示需要在什么级别保存该注解信息 可选的RetentionPolicy参数包括: SOURCE –> 注解被编译丢弃 CALSS –> 注解在class文件中可以用,但会被VM丢弃 RUNtIME –> VM将在运行时期保留注解,可以通过反射机制读取注解的信息 |
@Documented | 将此注解包含在Javadoc中 |
@Inherited | 允许子类继承父类中的注解,默认为false |
需要注意CLass,RUNTIME
1.1 RUNTIME,运行时注解
运行时注解,简单案例:
//定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
public int id();
public String description() default "no description";
}
//使用
public class PasswordUtils {
@UseCase(id=47,description = "Password must contain at least one numeric")
public static boolean validatePassword(String password){
return (password.matches("\\w*\\d\\w*"));
}
@UseCase(id = 48)
public static String encryptPassword(String password){
return new StringBuilder(password).toString();
}
@UseCase(id= 49,description = "New passwords can't equals previously used ones")
public static boolean checkForNewPassword(List<String>list,String password){
return !list.contains(password);
}
}
编写注解处理器:
public class UseCaseTracker {
public static void trackUseCases(List<Integer>lsit,Class<?>cl){
for (Method m : cl.getDeclaredMethods()){
UseCase uc = m.getAnnotation(UseCase.class);
if (null != uc){
System.out.println("Found use case-"+uc.id() +" "+uc.description());
lsit.remove(new Integer(uc.id()));
}
}
for (int i:lsit){
System.out.println("Warning : Missing use case - "+i);
}
}
public static void main(String[]args){
List<Integer>list = new ArrayList<>();
Collections.addAll(list,47,48,49,50);
trackUseCases(list,PasswordUtils.class);
}
}
利用两个反射方法:getDeclaredMethods()
和getAnnotation()
getAnnotation()
方法返回的结果就是注解对象
,这里就是UseCase
。如果被注解的方法上没有该类型的的注解,返回null
运行结果:
Found use case-47 Password must contain at least one numeric
Found use case-48 no description
Found use case-49 New passwords can't equals previously used ones
Warning : Missing use case - 50
1.2 CLASS,编译时注解 <p>
挖坑 ,等会用了再,来填坑
1.3 注解元素 <p>
在上面的例子中,@UseCase
是由UseCase.java
定义的,在里面有int
元素id
,以及String
元素description
在注解中,注解元素可以使用的类型:
- 所有的的基本数据类型(
int
,float
,boolean
等) - String
- enum
- Annotation
使用其他的类型,编译器会报错。注意:不允许使用任何包装类型,由于存在自动打包,这并不是限制。
注解也可以作为元素的类型,也就是说注解可以嵌套
1.4 默认值限制 <p>
编译器对注解元素的默认值很挑剔:
- 元素不能有不确定的值。元素要么有默认值,要么在使用注解时提供了值
- 非基本类型的元素,无论是在代码中声明时,还是在注解接口中定义默认值时,都不能为
null
约束:
这些限制导致无法直接表现一个元素的存在和确实状态
因为在每个注解的声明中,所有的元素的都存在,并且又确定的值
为避开这个约束,可以自己定义一些特殊的值来标示元素存在或者缺失,例如:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimulatingNull{
public int id() default -1;
public String description() default "";
}
在定义注解时,这是一个习惯用法
2.最后 <p>
编译时注解还要再次进行学习,感觉比运行时注解要难,回头进行学习
本人很菜,有错误请指出
共勉 :)