butterknife源码分析:如何处理注解—反射与注解处理器

本文深入探讨了Java的注解处理,包括反射机制和注解处理器AbstractProcessor。通过反射可以在运行时获取注解信息,而AbstractProcessor则在编译时处理注解,如ButterKnife框架。文章详细解释了Element与TypeMirror的区别,并通过实例展示了如何使用AbstractProcessor创建自定义注解处理器。
摘要由CSDN通过智能技术生成

butterknife源码分析系列:
谈一谈Java的注解
http://blog.csdn.net/u012933743/article/details/54909590
如何处理注解—反射与注解处理器
http://blog.csdn.net/u012933743/article/details/54972050
代码分析
http://blog.csdn.net/u012933743/article/details/64437988

有时,我们希望在程序运行或者编译时能获取注解的值,并做一些处理。如何想运行时处理注解,需要通过反射(Reflect),此时要将@Retention设置为RUNTIME;如果是编译时,需要用到注解处理器(AbstractProcessor),并将@Retention需要设置为CLASS。


反射

反射机制允许在运行时发现和使用类的信息。Class类与java.lang.reflect一起对反射的概念进行了支持,允许在运行时利用反射达到:

  • 判断任意一个对象所属的类;
  • 构造任意一个类的对象;
  • 判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  • 调用任意一个对象的方法

其实我觉得反射是个很bug般的存在,连private的都能进行操作。不过,反射会对性能有影响,因为JVM无法对反射部分的代码进行优化。在http://docs.oracle.com/javase/tutorial/reflect/中有说到:

Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

这里举个简单的栗子对反射的运用进行介绍。

注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ReflectParam {

    String value() default "nobody";

}

反射是在运行中获取类的信息,因此需要将注解的声明周期设置为RUNTIME,@Retention(RetentionPolicy.RUNTIME)。

Main函数

public class ReflectMain {

    @ReflectParam("jerry")
    public String userName;

    public static void main(String[] args) {
        ReflectMain main = new ReflectMain();
        ReflectParam annotation = null;
        try {
            Class clazz = main.getClass();
            Field field = clazz.getField("userName");
            annotation = field.getAnnotation(ReflectParam.class);
            System.out.print(annotation.value());
        } catch (NoSuchFieldException e) {
            System.out.print("no such field");
        }
    }

}

ReflectParam是修饰域变量的注解(@Target(ElementType.FIELD)),因此需要先通过反射获取Field。Field、Method、Constructor内都有getAnnotation来获取注解的方法。获取到ReflectParam注解后,直接通过注解内定义的方法来获取注解的值,这里我们定义的方法是value()。

输出结果如下, 因此通过反射可以获取到注解的值并做一些处理。

jerry
Process finished with exit code 0

在写这篇博客时,突然想到比较二的问题,这里也跟大家分享下。我们的ReflectParam注解内的value方法是没有用权限关键词修饰的,那位什么在Main函数内可以直接用annotation.value()来调用呢?不加权限关键词的默认难道不是default(包权限)吗?

其实这是一个陷阱,@interface默认继承自java.lang.annotation.Ann

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值