zoukankan      html  css  js  c++  java
  • 廖雪峰Java4反射与泛型-2注解-3处理注解

    1.处理注解

    • 注解本身对对代码逻辑没有任何影响
    • SOURCE类型的注解在编译期就被丢掉了
    • CLASS类型的注解仅保存在class文件中
    • RUNTIME类型的注解在运行期可以被读取
    • 如何使用注解由工具决定

    因此如何处理注解只针对RUNTIME类型的注解
    如何读取RUNTIME类型的注解
    思路:

    • Annotation也是class
    • 所有Annotation继承自java.lang.annotation.Annotation
    • 使用反射API,就可以获取

    2.使用反射API读取Annotation

    Report.java

    package com.reflection;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Report {
        int type() default 0;
        String level() default "info";
        String value() default "";
    }
    
    

    Person.java

    package com.reflection;
    @Report(type=1,level = "error")
    public class Person {
    
    }
    
    • 方法1: 判断某个Annotation是否存在,存在再打印注解的信息
      • Class.isAnnotationPresent(Class)
      • Field.isAnnotationPresent(Class)
      • Method.isAnnotationPresent(Class)
      • Constructor.isAnnotationPresent(Class)
    package com.reflection;
    
    public class Main {
        public static void main(String[] args){
            Class cls = Person.class;
            if (cls.isAnnotationPresent(Report.class)){
                Report report = (Report) cls.getAnnotation(Report.class);
                int type = report.type();
                String level = report.level();
                System.out.println(type+"	"+level);
            }
        }
    }
    
    • 方法2:获取某个Annotation,注解对象不为空,再打印注解的信息
      * Class.getAnnotation(Class)
      * Field.getAnnotation(Class)
      * Method.getAnnotation(Class)
      * Constructor.getAnnotation(Class)
      * getParameterAnnotations()
    package com.reflection;
    
    public class Main {
        public static void main(String[] args){
            Class cls = Person.class;
            Report report = (Report) cls.getAnnotation(Report.class);
            if (report != null){
                int type = report.type();
                String level = report.level();
                System.out.println(type+ "	" + level);
            }
        }
    }
    

    3.读取方法参数的Annotation:

    NotNull.java

    package com.reflection;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    public @interface NotNull{
    
    }
    

    Range.java

    package com.reflection;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Range{
        int min() default 1;
        int max() default  100;
    }
    

    Hello.java

    package com.reflection;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    public class Hello {
        public String hello(@NotNull String name,@NotNull @Range(max = 5) int age){
            return name+"	"+age;
        }
    }
    

    TestHello.java

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;
    
    public class TestHello {
        public static void main(String[] args) throws Exception{
            Class cls = Hello.class;
            Method m = cls.getMethod("hello", String.class, int.class);
            //方法的参数本身可以看作是一个数组,每一个参数又可以定义多个注解。因此一次获取所有方法的注解,要用2维数组来表示
            Annotation[][] annos = m.getParameterAnnotations();
            Parameter[] params = m.getParameters();
    
            for(int i=0;i<annos.length;i++){
                System.out.print(params[i]+"	{");
                for(Annotation anno:annos[i]){
                    System.out.print(anno.toString()+"	");
                }
                System.out.print("}");
                System.out.println();
            }
        }
    }
    

    4.读取字段的Annotation

    NotNull.java

    package com.reflection;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface NotNull{
        
    }
    

    Range.java

    package com.reflection;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Range{
        int min() default 1;
        int max() default  100;
    }
    

    Person.java

    package com.reflection;
    
    public class Person{
        @NotNull
        public String name;
        @Range(max=20)
        public int age;
    
        public Person(String name,int age){
            this.name=name;
            this.age = age;
        }
    
    }
    

    Main.java

    package com.reflection;
    //Java注解本身对代码逻辑并不产生任何影响,所以应用的这些注解并不会自动对name和age进行检查,我们需要自己的代码应用这些注解
    import java.lang.reflect.Field;
    public class Main{
        public static void main(String[] args) throws Exception{
            Person p1 = new Person("xiaoming",25);
            Person p2 = new Person(null,15);
            checkPerson(p1);
            checkPerson(p2);
        }
        static void checkPerson(Person p) throws Exception{
            System.out.println("check " +p + "...");
            Class cls = Person.class;
            for(Field f:cls.getFields()){
                checkField(f,p);
            }
        }
        static void checkField(Field f,Person p) throws Exception{
            if (f.isAnnotationPresent(NotNull.class)){
                Object r = f.get(p);
                if (r==null){
                    System.out.println("Error Field " + f.getName() + "is null...");
                }
            }
            if (f.isAnnotationPresent(Range.class)){
                Range range = f.getAnnotation(Range.class);
                int n = (Integer) f.get(p);//参见反射2field
                if(n < range.min() || n > range.max()){
                    System.out.println("Error Field " + f.getName()+ "is out of range...");
                }
    
            }
        }
    }
    

    5.总结:

    • 可以在运行期通过反射读取RUNTIME类型的注解,不要漏写@Retention(RetentionPolicy.RUNTIME)
    • 可以通过工具处理注解来实现相应的功能
      * 对JavaBean的属性值按规则进行检查
      * JUnit会自动运行@Test注解的测试方法

    请根据注解:

    • @NotNull检查该属性为非null
    • @Range检查整形介于minmax,或者检查字符串长度介于minmax
    • @ZipCode: 检查字符串是否全部由数字构成,且长度恰好为value

    实现对Java Bean的属性值检查。如果检查为通过,抛出异常

  • 相关阅读:
    关于MIME类型问题,浏览器请求到的资源是乱码
    关于vue切换用户,路由表不更新问题
    Flutter环境安装,ios真机调试
    vue使用trackingjs
    js的中文英文排序
    google无法播放mp4 chrome无法播放h264
    写在Blog前
    NOI2010Day1
    菜鸡KLC的中考游记
    ABC161 题解
  • 原文地址:https://www.cnblogs.com/csj2018/p/10403146.html
Copyright © 2011-2022 走看看