注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。
Java内置的标准注解和元注解
标准注解
- @Override,表示当前的方法定义将覆盖超类中方法,如果不小心拼写错误,或者方法签名对不上被覆盖的方法,编译器就会发出错误提示。
- @Deprecated,如果程序员使用了注解为它的元素,那么编译器会发出警告信息。
- @SuppressWarnings,关闭不当的编译期警告。
元注解
元注解专职负责注解其他注解。
- @Taraget,表示注解可以用到什么地方。可能的ElementType参数包括:
- CONSTRUCTOR:构造器
- FIELD:域声明(包括enum实例)
- LOCAL_VARIABLE:局部变量声明
- METHOD:方法声明
- PACKAGE: 包声明
- PARAMETER:参数声明
- TYPE:类、接口(包括注解类型)或enum声明
- @Retention,表示需要怎么什么级别保存该注解信息。可选的RetentionPolicy参数包括
- SOURCE :注解将被编译器丢失
- CLASS:注解在class文件中可用,但会被VM丢弃
- RUNTIME:VM将在运行期也保留注解,因此可以用过反射机制读取注解信息。
- @Documented,将此注解包含在javadoc中
- @Inherited 允许子嘞继承父类中的注解
定义注解
定义注解使用@interface(类中class,枚举用enum)后面紧根名字,例如:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
}
定义注解时需要用到元注解。@Targe表示定义的注解将应用到什么地方(例如一个方法或域),@Retention用来定义一个注解在哪一个级别可用。
注解元素
在注解中一般都会包含一些元素以及表示某些值。注解中可以出现的元素有:
- 任何的基本数据类型
- String
- Class
- enum
- Annotation
- 以上的类型的数组
如果使用了其他的类型,编译器就会报错。注意,也不允许使用包装类。
没有包含任何元素的注解称为标记注解。
元素的默认值
编译器对注解的元素有很严格的要求。元素不能有不确定的值,也就是说,元素必须要么具有默认值,要么在使用注解时提供了值。例子:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase{
public int id() ; // 没有默认值
public String description() default "no description"; // 具有默认值
}
//使用注解
public calss Test{
@UseCase(id = 1 , description = "method a")
public void a(){
}
@UseCase(id = 2) //description元素具有默认值,可以不用赋值,但id没有默认。 值,所以是一定要赋值的。
public void b(){
}
}
其次,对非基本数据类型的元素,无论在源代码中声明,或是在注解接口中定义默认值时,都不能用null作为其值。所以养成良好的习惯编码。如:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase{
public int id() default -1; // 一般用负数表示元素不存在
public String description() default ""; // 一般用“”表示元素不存在
}
注解处理器
如果没有用来读取注解的工具,那注解也不会比注释更有用。使用注解很重要的一部分就是编写注解处理器。在java SE5扩展了
通过反射
反射机制的API,以帮助帮助程序员构造这类的工具。
Class,Method,Field实现了AnnotationElement接口,所以通过反射得到Class ,Method ,Field的对象后,可以使用getAnnotation()方法返回指定的注解。如果没有使用注解,则返回null。
apt工具
也可以通过一个外部工具apt帮助程序员解析带有注解的java源代码。