然后在main函数中编码如下:
@Hello(value = "hello!")
public class Tester {
public static void main(String[] args) {
//获取Tester类上的注解对象
Hello annotation = Tester.class.getAnnotation(Hello.class);
//调用注解对象的value方法,并打印到控制台
System.out.println(annotation.value());
}
}
//输出结果:hello!
因为注解本质上继承了Annotation接口的接口,所有通过反射即getAnnotation方法去获取注解类的实例时,其实JDK是通过动态代理截至生成一个实现注解的代理类。所有我们可以进行调试。
找到临时代理类$Proxy1,反编译代码如下:
从反编译代码中可以看到动态代理类$Proxy1实现了Hello接口,并重新其所有方法,包括value方法及接口Hello从Annotation接口继承而来的方法。
在看Hello的字节码
Hello字节码显示确实继承了Annotation的接口。在flag字段中,我们可以看到,有个ACC_ANNOTATION标记,说明是一个注解,因此注解本质就是继承了Annotation的特殊接口。
5、总结
注解本质就是继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。通过动态代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。改方法会从memberValues这个map中索引出对应的值。而memberValues的来源是Java厂里池。