1. 什么是注解
也就是说,注解里存储着一些额外的数据,如果源代码中有这些注解,那么就可以将这些数据取出来,留以己用。
举个栗子:程序猿小A想追求设计组的小C,就找到了C的朋友小B,向她了解了一些C的喜好,最后B给了A一张纸条,说:这上面有C的电话、生日。
情况1:A在随后的日子里对C有了更深一步的了解,觉得她是个好女孩,于是想继续追求她,根据纸条上的生日信息和电话,在她生日那天,买了束花,向小C表白了。
情况2:随着A对C越来越多的了解,A觉得C并不是他理想中的另一半,就放弃了对她的追求,于是呢,当初那张写着小C电话和生日的纸条也就没什么用途了。
1.1 注解的格式
通过 @interface
关键字来定义,看起来和接口的定义很相似,并且注解也会被编译成class文件。
下面是定义一个@MyTest
注解:
public @interface MyTest {
}
1.2 元注解
元,会想到元祖这个词。注解,它的使用本身会受到限制,譬如说,注解存活的时间、什么情况下注解可以修饰类或者方法、注解有没有特殊作用等。元注解的作用就是用来限制其他注解的,规范其他一般注解的使用,可以说是一般注解的元祖。
Java 中内置了六种元注解,分别如下:
元注解 | 描述 |
---|---|
@Target | JDK1.5 引入,标注注解声明的类型,比如:方法声明、类声明等,详见下面的ElementType |
@Retention | JDK1.5 引入,注解存留的时间,比如:注解是否能保留到编译时,或者被保留到运行时,详见下面的RetentionPolicy |
@Documented | JDK1.5 引入,能够将注解中的元素包含到 Javadoc 中去 |
@Inherited | JDK1.5 引入,表示允许子类继承父类中的注解 |
@Repeatable | JDK1.8 引入,表明标记的注解可以多次应用于相同的声明或类型使用 |
@Native | JDK1.8 引入,用于对属性做提示 |
类型 | 解释 |
---|---|
ANNOTATION_TYPE | 应用于注解类型 |
CONSTRUCTOR | 应用于构造函数声明 |
FIELD | 应用于属性或enum实例 |
LOCAL_VARIABLE | 应用于局部变量声明 |
METHOD | 用于方法声明 |
PACKAGE | 应用于包声明 |
PARAMETER | 应用于方法的参数 |
TYPE | 应用于类、接口或者enum声明 |
类型 | 解释 |
---|---|
SOURCE | 注解只在源码阶段保留,在编译器编译时它将被丢弃忽视。 |
CLASS | 注解只被保留到编译进行的时候,不会被加载到JVM 中。 |
RUNTIME | 注解会被加载到JVM中,可以在程序运行时通过反射机制获取到注解的信息。 |
2. 自定义注解
大多数时候,我们主要是使用自定义注解,并且要有读取注解的处理器来获取注解中包含的信息。
2.1 自定义一个注解并通过反射获取注解的元素值
注解可以包含一些元素(形式类似接口方法),通过给这些元素赋值,使得程序可以在需要的时候获取到这些值 ,这其中用到的就是反射机制。
例如,下面自定义一个@Vip注解,它包含一个【vipPrice】元素,如果用户被@Vip注解标记,那么这个用户享受的就是VIP会员价格,即vipPrice的值。
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Vip {
/**
* VIP用户享有的价格
*/
double vipPrice();
}
public class VipUser extends User {
@Vip(vipPrice = 99.00)
private Double price;
...
}
public static void main(String[] args) throws Exception{
//获取 VipUser 的 price 属性
Field price = VipUser.class.getDeclaredField("price");
price.setAccessible(true);
//获取 @Vip 注解对象
Vip vip = price.getAnnotation(Vip.class);
//获取vipPrice,并打印到控制台
if (vip != null) {
double vipPrice = vip.vipPrice();
System.out.println(vipPrice);
}
}
99.0
Process finished with exit code 0
上述用到了两个反射方法:getDeclaredField()和getAnnotation(),其中getAnnotation()方法返回指定类型的注解对象,这里就是Vip,如果未使用该类型的注解,则返回null,随后,通过调用price()方法获取到vip对象中的price值。
另外,还可以为注解的元素设定默认值default,如:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Vip {
/**
* VIP用户享有的价格,默认值66.00
*/
double vipPrice() default 66.00;
}
2.2 注解元素的类型
上述例子中,注解元素price的类型是基本类型double,除此之外,注解可用的其他类型有:
- 基本型(int、float、boolean、long等)
- String
- 枚举类型enum
- class
- Annotation(注解可以作为元素的类型,即注解可以嵌套)
- 元素类型是上述类型的数组
【未完待续......】
版权声明:本文为博主原创文章,欢迎转载,转载请注明作者、原文超链接。