普通注解
@override
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@interface的作用其实是声明Override是注解,并继承Annonation接口,这个可以从反编译的文件看出。其实所有的注解都是继承了Annonation接口
元注解(meta-annotation)
元注解就是可以使用在注解上的注解
@Document
使用后,生成的javadoc会显示注解信息。
如,声明一个注解Log
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
在另一个方法使用该注解
public class Start {
@Log
public void start() {
}
}
使用命令 javadoc Start.java 得到javadoc的文件,打开index.html
如果Log注解中的@Document没有使用,则得到的index.html如下
@Retention
表示被修饰的注解在什么阶段保留
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
它的值是一个枚举类型,共三种
-
SOURCE
- 被修饰的注解,信息只保留在java文件中,编译后消失
-
CLASS
- 保留在编译后的class文件中
-
RUNTIME
- 既保留在class文件中,又保留在虚拟机的运行态中,可以通过反射读取
@Target
表示被修饰的注解可以使用在哪些位置
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
值也是一个枚举类型,但是是一个数组
- TYPE
- 表示该注解可以使用在类、接口(包括Annotation)、枚举上
- FIELD
- 字段(包括枚举常量)
- METHOD
- 方法
- ANNOTATION_TYPE
- 可以使用在注解上,比如元注解的target都是该值
@Inherited
表示被修饰的注解具有继承作用,比如某个类使用了被@Inherited修饰的注解,那么它的子类也会有该注解
如创建一个日志注解
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
使用该注解
@Log
public class Car {
}
创建子类
public class MyCar extends Car {
public static void main(String[] args) {
Class<MyCar> myCarClass = MyCar.class;
boolean annotationPresent = myCarClass.isAnnotationPresent(Log.class);
System.out.println(annotationPresent);
}
}
输出结果
true
注解的应用与反射
注解表面上其实只是标注一下,没有实际作用。通过反射可以获取使用在类或方法等上面的注解,然后根据业务判断不同的注解,实现不同的功能。
比如spring中的注解 @RequetMapping("/xxx")
当请求进入后,Spring会扫描某个类下的所有方法,获取其注解类型,以及注解中的值,判读是否与url相同,然后再反射执行该方法。