先来看一些用到的注解:
系统自带的
ButterKnife
以上是两种比较常见的注解。大家肯定也遇到过,今天要讲的是编译时的注解,先把基本概念搬出来晒一下:
APT
APT (Annotation Processing Tool) 是一种处理注释的工具,它对源代码文件进行检测找出其中的 Annotation,使用 Annotation 进行额外的处理。
Annotation 处理器在处理 Annotation 时可以根据源文件中的 Annotation 生成额外的源文件和其它的文件(文件具体内容由 Annotation 处理器的编写者决定), APT 还会编译生成的源文件和原来的源文件,将它们一起生成 class 文件。
在 JDK 1.5 之后,Java 语言提供了对注解(Annotation)的支持,这些注解和普通的 Java 代码一样,是在运行期间发挥作用的。在JDK 1.6 中实现了JSR-269 规范。提供了一组差入职注解处理器的标准 API 在编译期间对注解进行处理,我们可以把它看做是一组编译器的插件,在这些插件里面,可以读取,修改,添加抽象语法书中的任意元素。
三类注解:
- 标准 Annotation
包括 Override, Deprecated, SuppressWarnings,是java自带的几个注解,他们由编译器来识别,不会进行编译。- 元 Annotation
@Retention, @Target, @Inherited, @Documented,它们是用来定义 Annotation 的 Annotation。也就是当我们要自定义注解时,需要使用它们。- 自定义 Annotation
根据需要,自定义的Annotation。
自定义 Annotation:
@Retention: 定义注解的保留策略
- @Retention(RetentionPolicy.SOURCE)
SOURCE
该注解仅用于源码阶段,就是我们编写的java文件。- @Retention(RetentionPolicy.CLASS)
CLASS
该注解用于源码、类文件阶段。就是我们编写java文件和编译后产生的class文件。- @Retention(RetentionPolicy.RUNTIME)
RUNTIME
该注解用于源码、类文件和运行时阶段。
@Target:定义注解的作用目标
- @Target(ElementType.TYPE)
接口、类、枚举、注解- @Target(ElementType.FIELD)
字段、枚举的常量- @Target(ElementType.METHOD)
方法- @Target(ElementType.PARAMETER)
方法参数- @Target(ElementType.CONSTRUCTOR)
构造函数- @Target(ElementType.LOCAL_VARIABLE)
局部变量- @Target(ElementType.ANNOTATION_TYPE)
注解- @Target(ElementType.PACKAGE)
包
@interface 表示申明注解用的
写完了注解的知识,接下来我们写个 demo 简单跑一下,加深下理解。
先来看段代码
这段代码中我们看到使用了「@ClickAnnotation」这句代码。那为什么加了这句就会起作用呢?这就是前面讲到的使用了「@Target(ElementType.METHOD)」,作用目标就是在 method 上。后面包含了两个值,一个是 int 型的资源 id ,一个是 String 型。
看看这段代码运行结果
那么,上面添加的注解到底做了什么事情呢?我们看下 generated 中生成的代码,可以看到多了一个 MAinActivity$$PROXY 的文件。
先不关心这个文件是怎么来的,先打开看看里面是什么东西,打开后可以看到具体生成的代码:
看到这里,大家应该大致上能够了解为什么简单加了注解后会出现上面 gif 显示的效果。其实真正起作用的是这份 java 代码。而这份代码在编译的时候就已经生成了,所以 app 运行的时候就显示了 toast。
今天先写到这,下次聊聊这份 java 代码具体是怎么生成的。
Demo 源码这这边。大家可以先动手玩一下。这样有助于加深理解。
Demo 源码:https://github.com/ibrothergang/DemoAnnotation