一、注解
1.概念
对程序做解释
可以被其他程序(编译器)读取
@符号+黄色,还可以加参数值(@override、@SuppreddWarnings(value=“unchecked”)等)
使用在package、class、method、field等上面
通过反射+注解实现对元数据访问
Annotation类
2.内置注解
- @override:重写
- @Deprecated:表示不鼓励程序员使用这样的元素
- @SuppredWarnings:带参数,用来抑制编译时的警告信息??
3.元注解
负责注解其他注解,java定义了4个标准的mate-anntation类型,用来对annotation做说明。
@Target:描述注解使用范围
@Retention:表示需要在什么级别保存改注释信息,用户描述注解的生命周期
source
@Document:说明该注解包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
4.演示元注解用法:
此时注解MyAnnotation可以用在方法和类上、注解在运行时有效、生成在javadoc中,子类可以继承父类的注解。
5.自定义注解
自定义注解的步骤如下:
① 自定义注解
下面定义一个能识别字符串长度的注解,在自定义注解的上方添加元注解:
ElementType.FIELD:表示该注解在属性上使用
RetentionPolicy.RUNTIME:表示该注解到程序运行中仍然生效
在自定义注解中添加三个方法:
允许字符串的最小长度
允许字符串的最大长度
超出范围后的错误提示
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Length{ // 允许的字符串长度最小值 int min(); // 允许的字符串长度最大值 int max(); // 自定义错误提示 String errorMsg(); }
② 写自定义注解的解释器
public class LengthValidator { public static String validateField(Object object) throws IllegalAccessException { // 获取字段值 // 对本文来说就是Person的id、name、age三个字段 Field[] fields = object.getClass().getDeclaredFields(); // 逐个字段校验,看看哪个字段标了注解 for (Field field: fields){ // if判断:检查字段上面有没有标注@Length注解 if(field.isAnnotationPresent(Length.class)){ // 通过反射获取到该字段上标注的@Length的注解的详细信息 Length length = field.getAnnotation(Length.class); // 让我们在反射时看到私有变量 field.setAccessible(true); // 获取实际字段的值 int value = ((String)field.get(object)).length(); // 将实际字段的值和注解的标记值进行对比 if(value < length.min() || value > length.max()){ return length.errorMsg(); } } } return null; } }
③ 使用注解
public class Person { private String id; @Length(min = 3, max = 30, errorMsg = "姓名长度必须3-30之间") private String name; private Integer age; //Getter and Setter略 }
④ 让自定义注解生效
常规是用扫描包和类的方式扫描到Leng注解,然后让注解生效。
下面直接调用注解解释器,简单、直观。
public class AnnotationTest { public static void main(String[] args) throws IllegalAccessException { Person person = new Person(); person.setName("13"); person.setAge(10); person.setId("001"); String validateField = LengthValidator.validateField(person); if(validateField == null) System.out.println(person); else System.out.println(validateField); } }
总结:
- 注解本质是一个接口,注解内的方法使用起来更像属性。
- 使用@interface自定义注解,自动继承了java.lang.anntation.Anntation接口。
- 注解让代码变得简洁,开发效率更高。
- 使用注解比不使用注解背后的逻辑变得更加复杂,运行速度可能会更低。