Java使用自定义注解并处理注解

电玩女神 2021-09-21 23:28 404阅读 0赞

目录

  • 元注解
  • 自定义注解
  • 使用注解
  • 处理注解的方法
  • 测试使用

元注解

负责注解其他注解, Java定义了4个标准的meta-annotation类型, 他们被用来对其他annotation类型作说明

在 java.lang.annotation中可以找到

  • @Target: 用于描述注解的范围(可以用在什么地方)
  • @Retention: 表示需要在什么级别保存该注解, 用于描述注解生命周期

    • SOURCE < CLASS < RUNTIME
  • @Document: 说明该注解是否包含在javadoc中
  • @Inherited: 说明子类可以继承父类中该注解

@Target

最常用的元注解是@Target。使用@Target可以定义Annotation能够被应用于源码的哪些位置:

  • 类或接口:ElementType.TYPE
  • 字段:ElementType.FIELD
  • 方法:ElementType.METHOD
  • 构造方法:ElementType.CONSTRUCTOR
  • 方法参数:ElementType.PARAMETER

例如,定义注解 @MyAnnotation 可用在方法上,我们必须添加一个 @Target(ElementType.METHOD)

@Retention

另一个重要的元注解@Retention定义了Annotation的生命周期:

  • 仅编译期:RetentionPolicy.SOURCE
  • 仅class文件:RetentionPolicy.CLASS
  • 运行期:RetentionPolicy.RUNTIME

如果 @Retention 不存在,则该 Annotation 默认为 CLASS。因为通常我们自定义的 Annotation 都是RUNTIME,所以,务必要加上 @Retention(RetentionPolicy.RUNTIME) 这个元注解

  1. /** * 定义一个注解 * Target: 表示我们的注解可以用在那些地方 * Retention: 表示注解在什么时候有效, 源码,class, 运行时 * Documented: 表示是否将我们的注解生成在JavaDoc中 * Inherited: 表示子类可以继承父类的注解 */
  2. @Target(value = { ElementType.METHOD})
  3. @Retention(value = RetentionPolicy.RUNTIME)
  4. @Documented
  5. @Inherited
  6. @interface MyAnnotation { }

自定义注解

  1. import java.lang.annotation.ElementType;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. import java.lang.annotation.Target;
  5. @Retention(RetentionPolicy.RUNTIME)
  6. @Target(ElementType.FIELD)
  7. public @interface Range {
  8. int min = 1;
  9. int max = 7;
  10. String msg = "长度不能小于" + Range.min + "或者大于" + Range.max;
  11. String message() default msg;
  12. int min() default min;
  13. int max() default max;
  14. }

使用注解

  1. public class Person {
  2. @Range
  3. public String name;
  4. @Range(min = 22, max = 50, message = "年龄不能小于22或者大于50")
  5. public Integer age;
  6. @Range(min = 3, max = 20, message = "长度不能小于3或者大于20")
  7. public String city;
  8. public Person() { }
  9. public Person(String name, Integer age, String city) {
  10. this.name = name;
  11. this.age = age;
  12. this.city = city;
  13. }
  14. // 此处省略 get/set ...
  15. }

处理注解的方法

  1. import java.lang.reflect.Field;
  2. public class RangeCheck {
  3. public static void check(Person person) throws IllegalAccessException, NullPointerException, IllegalArgumentException {
  4. // 使用反射获取所有字段并遍历
  5. for (Field field : person.getClass().getFields()) {
  6. // 获取字段上的注解
  7. Range range = field.getAnnotation(Range.class);
  8. // 判断该字段是否使用了注解
  9. if (range != null) {
  10. // 获取字段的值, 这里可能会抛出 IllegalAccessException 访问权限异常
  11. Object value = field.get(person);
  12. System.out.println(field.getName() + " value--> " + value);
  13. // 判断参数是否为空
  14. if (value == null) {
  15. throw new NullPointerException(field.getName() + "不能为空");
  16. }
  17. // String类型校验
  18. else if (value instanceof String) {
  19. // 如果是String类型就强转
  20. String s = (String) value;
  21. // 判断该值是否满足 @Range的min/max
  22. if (s.length() < range.min() || s.length() > range.max()) {
  23. throw new IllegalArgumentException("参数异常: " + field.getName() + range.message());
  24. }
  25. }
  26. // Integer 类型校验
  27. else if (value instanceof Integer) {
  28. Integer i = (Integer) value;
  29. if (i < range.min() || i > range.max()) {
  30. throw new IllegalArgumentException("参数异常: " + field.getName() + range.message());
  31. }
  32. }
  33. }
  34. }
  35. }
  36. }

测试使用

  1. class DemoApplicationTests {
  2. public static void main(String[] args) {
  3. Person person = new Person("Hello", 18, "深圳");
  4. try {
  5. RangeCheck.check(person);
  6. }
  7. // catch (IllegalAccessException e) {
  8. // e.printStackTrace();
  9. // }
  10. // catch (IllegalArgumentException e) {
  11. // e.printStackTrace();
  12. // String message = e.getMessage();
  13. // System.out.println("非法参数异常: --> " + message);
  14. // }
  15. // catch (NullPointerException e) {
  16. // e.printStackTrace();
  17. // String message = e.getMessage();
  18. // System.out.println("空指针异常: --> " + message);
  19. // }
  20. catch (Exception e) {
  21. e.printStackTrace();
  22. if (e instanceof IllegalArgumentException) {
  23. System.out.println("非法参数异常");
  24. }
  25. String message = e.getMessage();
  26. System.out.println("所有异常: --> " + message);
  27. }
  28. }
  29. }
  30. /*******************某个字段不符合要求就会抛出异常********************/
  31. java.lang.IllegalArgumentException: 参数异常: age年龄不能小于22或者大于50
  32. at com.pro.pojo.RangeCheck.check(RangeCheck.java:35)
  33. 非法参数异常
  34. 所有异常: --> 参数异常: age年龄不能小于22或者大于50
  35. 2021-04-19 15:23:27.599 INFO 5604 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'

发表评论

表情:
评论列表 (有 0 条评论,404人围观)

还没有评论,来说两句吧...

相关阅读