美文网首页
10.注解(Thinking in java学习十)

10.注解(Thinking in java学习十)

作者: Vinson武 | 来源:发表于2020-04-16 14:03 被阅读0次

    基本概念

    1. 定义:注解(也称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。

    2. 注解在一定程度上是在把元数据和元代码文件结合在一起。通过使用注解,我们可以把这些元数据保存在Java源代码中,并利用annotation API为自己的注解构造处理工具。

    3. Java内置了三种定义在java.lang中的注解

    • @Override,覆盖超类
    • @Deprecated,过期注释
    • SuppressWarnings,关闭不当的编译器的警告信息。

    另外还提供了==四种元注解==,专门负责新注解的创建。

    • @Targer:表示该注解可以用于什么地方。
    • @Retention:表示需要在什么级别保存该注解信息。
    • @Documented:将此注解包含在Javadoc中。
    • @Inherited:允许子类继承父类中的注解。

    @Targer


    image.png

    @Retention


    image.png

    基本语法

    定义注解

    @Targer(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface UserCase{
       //注解元素
        public int id();
        public String desc() default "no desc"; //默认值
    }
    

    注解的定义看起来很像接口的定义,注解也将会编译成class文件。

    注解的元素看起来就像接口的方法,唯一的区别是你可以为其指定默认值。

    没有元素的注解称为标记注解。

    注解使用

    public class Test{
        @UserCase(id = 47, desc = "xxxx")
        public boolean testMet(String str){
            ...
            return true;
        }
    }
    

    注解的元素在使用时表现为名-值对的形式,并需要置于@UserCase声明之后的括号内。

    编写注解处理器

    注解元素

    注解元素的类型有以下几种:

    • 所有基本类型(int, float等)
    • String
    • Class
    • enum
    • Annotation(注解)
    • 以上类型的数组

    如果使用其他类型,编译器会报错。注意,也不能使用包装类型。

    默认值限制

    编译器对注解元素默认值要求较高

    • 首先,元素不能有不确定的值。即元素要么具有默认值,要么在使用注解时提供元素的值。
    • 其次,对于非基本类型的元素,定义默认值都不能以null作为其值。(这个约束使得处理器很难表现一个元素的存在或缺失,只能自己定义一些特殊值,比如空字符串或负数来表示元素不存在)

    注解不支持继承,不能使用关键字extends来继承某个@interface。

    实现处理器

    一个简单的原始注解处理器

    public class UseCaseTraker{
        public static void useCaseTrakers(List<Integer> useCases, Class<?>cl){
            for(Method m : cl.getDeclaredMethods()){
                UseCase uc = m.getAnnotation(UseCase.class);
                if(uc !=null){
                    System.out.println(uc.id() + " " + uc.desc());
                    useCase.remove(new Integer(uc.id()));
                }
            }
            for(int i:useCase){
                System.out.println("current case " + i);
            }
        }
        public static void main(String[] args){
            List<Integer>useCase = new ArrrayList<Integer>();
            Collections.addAll(useCase, 47, 48);
            trackUseCase(useCase, Test.class);
        }
    }
    //输出: 47 xxxx
    //current case 48
    

    getAnnotation(Class<A> annotationClass)获得注解

    getDeclaredAnnotations()获得注解元素

    Java自定义注解是通过运行时靠反射获取注解

    处理器的写法有固定的套路,继承AbstractProcessor。

    public class MyProcessor extends AbstractProcessor {
     
        @Override
        public synchronized void init(ProcessingEnvironment processingEnv) {
        //当我们编译程序时注解处理器工具会调用此方法并且提供实现ProcessingEnvironment接口的对象作为参数。
            super.init(processingEnv);
        }
     
        @Override
        public Set<String> getSupportedAnnotationTypes() {
            Set<String> types = new LinkedHashSet<>();
            types.add(UserCase.class.getCanonicalName());//返回该注解处理器支持的注解集合
            return types;
    
        }
     
        @Override
        public SourceVersion getSupportedSourceVersion() {
            return SourceVersion.latestSupported();
        }
     
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            //处理注解
            return true;
        }
    }
    
    • init(ProcessingEnvironment processingEnv) 被注解处理工具调用,参数ProcessingEnvironment 提供了Element,Filer,Messager等工具
    • getSupportedAnnotationTypes() 指定注解处理器是注册给那一个注解的,它是一个字符串的集合,意味着可以支持多个类型的注解,并且字符串是合法全名。
    • getSupportedSourceVersion 指定Java版本
    • process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) 这个也是最主要的,在这里扫描和处理你的注解并生成Java代码,信息都在参数RoundEnvironment 里了。

    注册注解处理器


    image.png

    google提供了一个注册处理器的库

    compile 'com.google.auto.service:auto-service:1.0-rc2'
    

    一个注解搞定:

    @AutoService(Processor.class)
    public class MyProcessor extends AbstractProcessor {
          ...
    }
    

    相关文章

      网友评论

          本文标题:10.注解(Thinking in java学习十)

          本文链接:https://www.haomeiwen.com/subject/koyrvhtx.html