基本语法
定义注解
|
元注解
定义注解时,需要一些元注解
@Target
定义你的注解应用于什么地方
- 构造器的声明(CONSTRUCTOR)
- 域声明(FIELD)
- 局部变量声明(LOCAL_VAIABLE)
- 方法声明(METHOD)
- 包声明(PACKAGE)
- 参数声明(PARAMETER)
- 类,接口,或enum声明(TYPE)
@Retention
定义该注解在哪一个级别可用
- 源代码(SOURCE) 注解将被编译器丢弃
- 类文件(CLASS) 注解在class文件中可用,但会被vm丢弃
- 运行时(RUNTIME) vm在运行时也保留注解,可用通过反射读取注解信息
元素
在注解中,一般都会包含一些元素以表示某些值。当分析处理注解时,程序或者工具可以利用这些值,注解的元素看起来就像接口的方法,唯一的区别就是你可以为其指定默认值,没有元素的注解称为标记注解
注解可用的类型有
- 基本数据类型
- String
- Class
- enum
- Annotation
- 以上类型的数组
|
description
元素有一个默认值,如果在注解某个方法时没有给出description的值,则该注解的处理器就会使用此元素的默认值
|
约束
编译器对元素的默认值有些过分挑剔。首先,元素不能有不确定的值,也就是说,元素必须要么具有默认值,要么使用注解时提供的元素的值。
其次,对于非基本类型的元素,无论是在原代码中声明时,或是在注解接口中定义默认值时,都不能以null作为其值。这个约束使得处理器很难表现为一个元素的存在或缺失的状态,因为在每个注解的声明中,所有的元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能自己定义一些特殊的值,例如空字符串或者负数,表示某个元素不存在。
注解处理器
如果没有用来读取注解的工具,那注解也不会比注释更有用。使用注解的过程中,很重要的一个部分是创建于使用注解处理器
,JDK1.5之后便提供了反射机制,以帮助程序员构造这类工具。同时,他还提供了一个外部工具apt帮助程序员解析带有注解的java代码
反射
在学习类型信息的时候见过这些方法,就不赘述
apt处理注解
这里在thinking in java中使用的还是AnnotationProcessor
作为处理器的基类,是com.sun.mirror.*
包下的类,在这里使用最新的javax.annotation.processing.AbstractProcessor
=> AbstractProcessor
,有必要提一下ButterKnife
和EventBus
也是采用了编译时注解的技术来减少反射带来的性能损耗,但是apt只能自动生成代码,运行的时候需要主动调用
|
可以看到,大概的过程通过类名创建代理类的对象(也是反射,但是只是在构造的时候使用constructor.newInstance
),在代理类对象的构造函数中完成了view的绑定过程