致敬。参考:https://www.cnblogs.com/acm-bingzi/p/javaAnnotation.html
一.注解的定义
注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后某个时刻非常方便地使用这些数据。
注解(Annotation)是java5开始引入的新特性,它们可以提供用来完整地描述程序所需的信息,而这些信息是无法用Java来表达的。因此,注解使的我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息。注解可以用来生成描述符文件,甚至或是新的类定义,并且有助于减轻编写“样板”代码的负担。通过使用注解,我们可以将这些元数据保存在Java源代码中,并利用annotation API为自己的注解构造处理工具,同时,注解的优点还包括:更加干净易读的代码以及编译期类型检查等。
二.注解的作用
1.生成文档。这是最常见的,也是Java最早提供的注解。常见的注解有@param @return @see等
2.跟踪代码依赖性,实现替代配置文件功能。
3.在编译时进行格式检查。如@override放在方法前,如果这个方法并不是覆盖了超类方法,则编译时就能检查出。
三.注解的原理
注解的本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValue的来源是Java常量池。
四.Java5内置注解(标准注解)
Java5内置的三种注解,定义在java.lang中
1.@Override,表示当前的方法定义将覆盖超类中的方法。如果不小心写错了,或者方法签名对不上被覆盖的方法,编译器就会发出错误提示
2.@Deprecated,如果程序员使用了注解为它的元素,那么编译器就会发出警告信息。
3.@SuppressWarnings,关闭不当的编译器警告信息。在Java5之前的版本中,也可以使用该注解,不过会被忽略不起作用。
五.元注解
1.@Target 表示该注解可以用在什么地方。可能的ElementType参数包括:
1.1 CONSTRUCTOR 构造器的声明
1.2 FIELD 域声明(包括enum实例)
1.3 LOCAL_VARIABLE 局部变量声明
1.4 METHOD 方法声明
1.5 PACKAGE 包生命
1.6 PARAMETER 参数声明
1.7 TYPE 类,接口(包括注解类型)或emum声明
2.@Retention 表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
2.1 SOURCE 注解将被编译器丢弃
2.2 CLASS 注解在class文件中可用,但会被VM丢弃
2.3 RUNTIME VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息
3.@Documented 将此注解包含在Javadoc中
4.@Inherited 允许子类继承父类中的注解
六.测试
package com.yexiaobai.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Person {
/**
* 姓名
* @return
*/
String name();
/**
* 年龄
* @return
*/
int age();
}
package com.yexiaobai.annotation;
@Person(name="yexiaobai", age=20)
public class TestAnnotation {
public static void print(Class clazz) {
System.out.println(clazz.getName());
Person person = (Person) clazz.getAnnotation(Person.class);
if (person != null) {
System.out.println("name==>" + person.name() + "==>age==>" + person.age());
} else {
System.out.println("person is no found!");
}
}
public static void main(String[] args) {
TestAnnotation.print(TestAnnotation.class);
}
}
结果
com.yexiaobai.annotation.TestAnnotation
name==>yexiaobai==>age==>20