2.5 注解
2.5.1 注解简介
Annotation是Java提供的一种元程序中的元素关联任何信息和元数据(metadata)的途径和方法。Annotation(注解)是一个接口,程序可以在编译期通过AbstractProcessor处理注解元素,或者运行期通过反射来获取指定程序元素的Annotation对象,然后通过Annotation对象来获取其中的元数据。
在Annotation中,成员以无参数的方法的形式被声明,其方法名和返回值定义了该成员的名字和类型。
2.5.2 元注解
在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法。元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,它们被用来提供对其它annotation类型作说明:@Target,@Retention,@Documented,@Inherited,这里我们看一下Target和Retention:
Target
Target说明了Annotation所修饰的对象范围:Annotation可被用于packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。其取值(ElementType)有:
- CONSTRUCTOR:用于描述构造器
- FIELD:用于描述域
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型)或enum声明
Retention
Retention定义了该Annotation被保留的时间长短:其取值(RetentionPolicy)有:
- SOURCE:在源文件中有效(即源文件保留)
- CLASS:在class文件中有效(即class保留)
- RUNTIME:在运行时有效(即运行时保留)
2.5.3 自定义注解
使用@interface自定义注解时,自动继承了Annotation接口,由编译程序自动完成其他细节。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数,方法的名称就是参数的名称,返回值类型就是参数的类型,返回值类型只能是基本类型、Class、String、enum,Annotation以及以上类型的数组,可以通过default来声明参数的默认值。简单的自定义注解和使用注解实例:
//定义注解FruitName
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
String value() default "";
}
//定义注解FruitColor
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {
public enum Color {BLUE, RED, GREEN};
Color fruitColor() default Color.GREEN;
}
//使用注解FruitName,FruitColor
public class Apple {
@FruitName("Apple")
private String appleName;
@FruitColor(fruitColor=Color.RED)
private String appleColor;
public void setAppleColor(String appleColor) {
this.appleColor = appleColor;
}
public String getAppleColor() {
return appleColor;
}
public void setAppleName(String appleName) {
this.appleName = appleName;
}
public String getAppleName() {
return appleName;
}
public void displayName(){
System.out.println("水果的名字是:苹果");
}
}
注解元素的默认值
注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此使用空字符串或0作为默认值是一种常用的做法。一般会定义一些特殊的值,例如空字符串或者负数,以此表示某个元素不存在。
2.5.4 注解处理器
使用注解的过程中,很重要的一部分就是创建注解处理器。根据Retention的取值,注解处理器可以分为编译期处理,运行期处理。
运行期处理
Java扩展了反射API,新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:Class、Constructor、Field、Method和Package。AnnotatedElement声明了以下四个方法:
- <T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回该程序元素上存在的、指定类型的注解。
- Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
- boolean isAnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
- Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注,该方法将忽略继承的注释。
下面看一个简单的注解处理器:
//该例使用上面定义的注解,定义注解处理器
public class FruitInfoProcessor {
public static void getFruitInfo(Class<?> clazz){
String strName="fruit name: ";
String strColor="fruit color: ";
Field[] fields = clazz.getDeclaredFields();
for(Field field :fields){
if(field.isAnnotationPresent(FruitName.class)){
FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
strName = strName + fruitName.value();
System.out.println(strName);
} else if(field.isAnnotationPresent(FruitColor.class)){
FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);
strColor = strColor + fruitColor.fruitColor().toString();
System.out.println(strColor);
}
}
}
}
编译期处理
总结:Java注解的基础知识点基本都过了一遍,最后用下面一张思维导图总结
网友评论