JAVA 注解(Java Annotation)
刚学 java 的时候,就接触了各种的 java 注解,那时候,不是很明白注解的原理,只能说,知道是那么回事,最近在折腾 apt 相关的内容,就重新复习了一遍。
注解的定义
注解是,类似 class interface 一样的类型,其定义解释可以参考 https://docs.oracle.com/javase/1.5.0/docs/guide/language/annotations.html
java 用 @interface 创建注解,例如如下:
public @interface DebugLog {
}
这里创建了 DebugLog 这个注解类.
元注解
元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它的注解上面。
元注解有以下五种:@Retention、@Documented、@Target、@Inherited、@Repeatable
@Retention
Retention 的英文意为保留期的意思。当 @Retention 应用到一个注解上的时候,它规定了了这个注解的的存活时间
它的取值如下:
- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们
@Documented
顾名思义,这个元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去。
@Target
Target 是目标的意思,@Target 指定了注解运用的位置
@Target 有下面的取值
- ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
- ElementType.CONSTRUCTOR 可以给构造方法进行注解
- ElementType.FIELD 可以给属性进行注解
- ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
- ElementType.METHOD 可以给方法进行注解
- ElementType.PACKAGE 可以给一个包进行注解
- ElementType.PARAMETER 可以给一个方法内的参数进行注解
- ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
@Inherited
Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
比如这样的例子:
@Inherited
public @interface TestAn1 {
}
@TestAn1
public class Animal {
}
public class Dog extends Animal{
}
TestAn1 注解被 @Inheritedpublic 元注解注解,意味着被 TestAn1 注解的的类,如果某个类是其子类,它也会拥有这个注解。也就是实例中,Animal 被TestAn1 注解,因为TestAn1 是@Inherited ,那么其子类 Dog 也会拥有这个注解。
@Repeatable
Repeatable 表示这个注解的属性,是否可以有多个值。@Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。
注解的属性
注解和类不一样,注解只要成员变量,也就是它的属性。它的定义形式是 无参数的方法,例如以下注解:
@Retention(SOURCE)
@Target({ANNOTATION_TYPE})
public @interface IntDef {
/** Defines the allowed constants for this element */
int[] value() default {};
/** Defines whether the constants can be used as a flag, or just as an enum (the default) */
boolean flag() default false;
}
这个是 Android support 包里面支持的注解,这个注解的value 属性是 int 类型的,例如在 Toast 里面用了这个
public class Toast {
static final String TAG = "Toast";
static final boolean localLOGV = false;
/** @hide */
@IntDef({LENGTH_SHORT, LENGTH_LONG})
@Retention(RetentionPolicy.SOURCE)
public @interface Duration {}
.......
public void setDuration(@Duration int duration) {
mDuration = duration;
mTN.mDuration = duration;
}
}
也就意味着,setDuration() 方法只能使用 LENGTH_SHORT LENGTH_LONG 这类的数值作为参数。