注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以 在稍后某个时刻非常方便地使用这些数据。
注解在一定程度上是在把元数据与源代码文件结合在一起,而不是保存在外部文档中这一 大的趋势之下所催生的。
注解可以提供用来完整地描述程序所需的倌息,而这些信息是无法用Java来表达的。因此,注解使得我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息。注解可以用来生成描述符文件,甚至或是新的类定义,并且有助于减轻编写“样板”代码的负担。通过使用注解,我们可以将这些元数据保存在 Java源代码中,并利用annotationAPI为自己的注解构造处理工具,同时,注解的优点还包括:更加干净易读的代码以及编译期类型检查等。
1.基本语法
1.1 定义注解
定义注解时,会需要一些元注解 (meta-annotation) ,如@Target和@Retention。@Target用来定义你的注解将应用于什么地方 (例如是一个方法或者一个域)。@Rectetion用来定义该注解在哪一个级别可用,在源代码中(SOURCE)、类文件中(CLASS)或者运行时(RUNTIME)。
在注解中,一般都会包含一些元素以表示某些值。当分析处理注解时,程序或工具可以利用这些值。注解的元素在使用时表现为名-值对的形式
没有元素的注解称为标记注解(markerannotation) 。
1.2 元注解
Java 目前只内置了三种标准注解(@Override,@Deprecated, @SuppressWarnings), 以及四种元注解。
大多数时候, 程序员主要是定义自己的注解, 并编写自己的处理器来处理它们。
2.编写注解处理器
使用注解的过程中, 很重要的一个部分就是创建与使用注解处理器。Java'SE5扩展了反射机制的API, 以帮助程序员构造这类工具。 同时, 它还提供了一个外部工具apt帮助程序员解析带有注解的Java源代码。
2.1 注解元素
注解元素可用的类型如下所示:
- 所有基本类型 (int, float, boolean等)
- String
- Class
- enum
- Annotation
- 以上类型的数组
2.2 默认值限制
编译器对元素的默认值有些过分挑剔。
- 首先,元素不能有不确定的值。 也就是说,元素必须要么具有默认值, 要么在使用注解时提供元素的值。
- 其次,对于非基本类型的元素,无论是在源代码中声明时, 或是在注解接口中定义默认值
时,都不能以null作为其值。 这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为在每个注解的声明中, 所有的元素都存在,并且都具有相应的值。 为了绕开这个约束,我们只能自己定义一些特殊的值, 例如空字符串或负数, 以此表示某个元素不存在。
2.3 生成外部文件
有些framework需要一些额外的信息才能与你的源代码协同工作,而这种情况最适合注解表现其价值了。
Web Service、自定义标签库以及对象/关系映射工具等, 一般都需要XML描述文件,而这些描述文件脱离于源代码之外。
如果使用注解的话, 你可以将所有信息都保存在JavaBean源文件中。
变通之道
2.4 注解不支持继承
2.5 实现处理器
3.使用apt处理注解
JDK7已经移除了apt和mirror API,取代 APT 的是更优的 JSR 269 API - "Pluggable Annotation Processing API".