Android-Annotation

2017-10-12  本文已影响0人  hyzhang98

什么是注解

注解之元注解

@Target
@Retention
@Inherited
@Documented

使用注解

基础知识
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation {
    int[] value();
    String name() default "";
}

public class Person {
    @MyAnnotation(1)
    int age;
    
    @MyAnnotation(name="John")
    String name;
}
编译时注解
//MyProcessor: 继承AbstractProcessor, 都是接口类型Processor, 这个类其实很好理解, 是java为我们提供
//的接口,当javac编译的时候会调用你配置好的Processor类去进行编译期注解的处理, 不然你只定义Annotation谁
//知道应该怎么处理它呢?所以我们必须要自己实现Processor,也叫注解处理器
//这个类做的事情其实是生成StaticAnnotation修饰的<变量名字, 类名>的json
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class MyProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        File file = new File("output.json");
        System.out.println("------------");
        try {
            for (TypeElement element : annotations) {
                System.out.print(element.getSimpleName() + " ");
            }
            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(StaticAnnotation.class);
            System.out.println(elements.size());
            if (elements.size() == 0) return false;
            Writer writer = new BufferedWriter(new FileWriter(file));
            writer.append("{\n");
            for (Element element : elements) {
                System.out.println(element.getSimpleName());
                System.out.println(element.getKind() == ElementKind.FIELD);
                if (element.getKind() == ElementKind.FIELD) {
                    writer.append(element.getSimpleName());
                    writer.append(": ");
                    writer.append(element.getEnclosingElement().getSimpleName());
                    writer.append("\n");
                }
            }
            writer.append("}\n");
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    //声明可以处理的注解的类型,添加到set里的必须是全名
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> set = new HashSet<>();
        set.add(StaticAnnotation.class.getCanonicalName());
        return set;
    }
}

//自定义的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface StaticAnnotation {
    int value();
}

//测试类
public class Student {
    @StaticAnnotation(3)
    String name;

    @StaticAnnotation(2)
    boolean isMale;
}

注:

运行时注解
public class TestClass {
    @MyAnnotation(1)
    private int value;

    public static void main(String[] args) {
        TestClass instance = new TestClass();
        Class clazz = instance.getClass();
        try {
            Field field = clazz.getDeclaredField("value");
            MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);
            Object o = field.get(instance);
            o = annotation.name();
            field.setInt(instance, annotation.name()[0]);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        System.out.println(instance.value);
    }
}

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    int[] name() default 0;
    int[] value();
}

上述例子利用注解对相应的实例变量进行了赋值,虽然反射也很烦,但是还是要比编译时生成代码写起来要更舒服一些的(也许是我对反射比元编程更习惯一些吧)

End

上一篇 下一篇

猜你喜欢

热点阅读