作者: DJ Walker-Morgan
批注能够消除样板代码,让源代码的可读性更高,并能提供级别更高的错误检查。从 EJB3 到 JUnit4 ,哪里都在使用它。本文就将告诉你如何使用它。
Java 5向Java引入了批注(Annotations),它的使用迅速成为现代Java开发中不可缺少的一部分。
为什么要发明批注?
问题:JAVA缺少元数据;缺乏将Java以外的代码嵌入到Java源代码文件里的能力等
解决方法一:JavaDoc (在代码里专门标记注释,能够提取出额外的信息,即文档,并转换成为JavaDoc文档)
首先有Doclet,目的是让人们扩展文档的输 出。
然后是Xdoclet,像使用标记一样使用JavaDoc来生成代码。
J2EE原来依靠很多样板代码(boilerplate code)把对象捆绑到J2EE框架里。
这些方案的问题:首先,注释里的标记不会进入最终的源代码,所以除非你生成代码来反映这些标记, 而且基于注释的标记在编译期间无法被IDE检查
于是:Java新增了批注。
什么是批注?
批注是用于Java语言的本机元数据标记 。
BaseExample:
public class BaseExample {
public BaseExample() {}
public void myMethod() {
System.out.println("This is the BaseExample");
}
}
现在,扩展BaseExample,并替代myMethod:
public class Example1 extends BaseExample {
public Example1() {}
@Overridepublic void myMethod() {
System.out.println("This is the Example1");
}
}
@Override的意思是“方法必须替代其超类中的一个方法;如果做不到这一点,那么就会有东西出错,使得编译器产生错误”。
没有@Override,代码照样会正常工作,但是假设有人修改 BaseExample,让myMethod带有参数。如果你没有使用@Override批注,代码仍然会被编译,隐藏了子类没有替代超类方法的问题。如果有@Override的话,你会在编译期间看到发生错误。
可以创建自己的批注标记
我们有一些简单的Java Beans程序,它们都带有不同的字符串字段。我们希望能够有一些通用窗体显示代码,它们能够用其他显示提示(比如宽度)来正确地标示这些字段。现在我们 可以编写一个超类,它能够提取出这个数据,比如说从一个在每个类里都带有一些静态支持方法的静态数组里,但是这也意味着要强制给代码分层。利用批注做到这 一点就要简单得多了。现在让我们从定义FormLabel.java里的FormLabel的批注开始:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public@interface FormLabel {String label();
int width() default 40;
}
你 应该注意到的第一件事是Java使用了它自己内置的一些批注来定批注:@Retention和@Target。@Retention用来定义通过设置 RetentionPolicy的值批注能够在构建-运行过程中存留多久。这里我们使用了RUNTIME,这意味着我们定义的批注将会在运行期间被保留在 代码里。RetentionPolicy.SOURCE将被用于一个我们希望被编译器使用然后抛弃的批注。RetentionPolicy.CLASS让 它们保留在生成的类文件里,但是能够在运行期间被Java虚拟机(JVM)访问到。
在默认情况下,你可以在代码里的任何地方都应用 批注。@Target批注让你能够将它限制在代码的特定部分里。在本文里,我们把目标瞄准了ElementType.METHOD,这意味着它只能够与方 法关联在一起。其他ElementTypes有CONSTRUCTOR、FIELD、LOCAL_VARIABLE、PACKAGE、PARAMETER 和TYPE,每个都能够把批注限制到该种类型的Java语言元素,所以例如,设置TYPE将只允许批注为定义过的这种类型,比如:
@OurAnnotation
public class OurAnnotatedClass {…
值得注意的是,@Target批注能够接受单个ElementType或者一个ElementType数组,如果你想要将批注限制为一系列语言元素的话。