Annotation是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。
通过使用Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。
Annotation可以像修饰符一样被使用,可以用于package、class、interface、constructor、method、member variable(成员变量)、parameter、local variable(局部变量)、annotation(注解),jdk 1.8之后,只要出现类型(包括类、接口、注解、枚举)的地方都可以使用注解了。
我们可以使用JDK以及其它框架提供的Annotation,也可以自定义Annotation。
1.示例
自定义注解MyAnnotation.java
package demo.annotation;
import java.lang.annotation.*;
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnnotation {
String test() default "default value";
}
创建一个类MyClass,在类和方法上加上刚才的注解
package demo.annotation;
@MyAnnotation(test = "类注解")
public class MyClass{
@MyAnnotation(test = "方法注解")
public void myMethod(){
}
}
创建MyClass的子类MySubClass
package demo.annotation;
public class MySubClass extends MyClass {
}
创建一个测试类:Test.java
package demo.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
try {
//获取类MyClass的注解
Class class0 = Class.forName("demo.annotation.MyClass");
Annotation[] annotations = class0.getAnnotations();
for (Annotation annotation:annotations) {
if(annotation instanceof MyAnnotation){
System.out.println("MyClass:"+((MyAnnotation) annotation).test());
}
}
//获取类MyClass中方法的注解
Method[] methods = class0.getMethods();
for(Method method:methods){
if(method.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
System.out.println("MyClass:"+myAnnotation.test());
}
}
//获取类MyClass子类MySubClass的注解
Class class1 = MySubClass.class;
if(class1.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = (MyAnnotation) class1.getAnnotation(MyAnnotation.class);
System.out.println("MySubClass:"+myAnnotation.test());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果如下
MyClass:类注解
MyClass:方法注解
MySubClass:类注解
可以说明:类、方法、子类都能获取自定义注解。
2.详解
自定义一个注解的时候,有4个注解@Target、@Retation、@Inherited、@Documented,其含义和选项如下:
@Target (注解可以作用的目标)
选项:(详见java.lang.annotation.ElementType)
ElementType.TYPE 类、接口(包括注解)、枚举
ElementType. FIELD 字段(包括枚举常量)
ElementType. METHOD 方法
ElementType. PARAMETER 参数
ElementType. CONSTRUCTOR 构造方法
ElementType. LOCAL_VARIABLE 局部变量
ElementType. ANNOTATION_TYPE 注解
ElementType. PACKAGE 包
ElementType. TYPE_PARAMETER 类型参数[ jdk1.8]
ElementType. TYPE_USE 类型使用[ jdk1.8]
注:当注解未指定Target值时,此注解可以使用任何元素之上
@Retention (注解可以作用的目标)
选项:(详见java.lang.annotation.RetentionPolicy)
RetentionPolicy.SOURCE 仅保留在源码,会被编译器丢弃。
RetentionPolicy.CLASS 仅保留在编译后的class文件中(默认值)。
RetentionPolicy.RUNTIME 注解保留在编译后的class文件中,并且运行时保留在JVM中,因此可以通过反射获取。
@Inherited (允许子类继承父类中的注解)
@Documented (注解会被javadoc处理,javadoc默认不包括注解)
3.自定义注解实战