定义
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
注解也叫元数据,正如上面所说,是一种代码级别的说明。
作用分类
- 编写文档: 通过代码中表示的元数据生成文档
- 代码分析:通过代码中的元数据对代码进行分析
- 编译检查:通过代码中的元数据让编译器能够实现基本的编译检查
注解的分类
按照运行的机制来分
- 源码注解:注解只在源码中存在,编译成.class文件就不存在了
- 编译时注解:注解在源码和.class文件中都存在(如:JDK内置系统注解)
- 运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解(如:Spring中@Autowried)
按照来源来分
JDK内置系统注解、元注解、自定义注解、第三方注解
自定义注解
- 成员类型是受限的,合法的类型包括原始类型及String,Calss,Anootation,Enumreation
- 如果注解已有一个成员,则成员名必须取名为Vaue(),在使用的时可以忽略成员名和赋值号(=)
- 注解类可以没有成员,没有成员的注解称为标识注解
/**
Java中提供了四种元注解,专门负责注解其他的注解,分别如下
@Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。可选的RetentionPoicy参数包括:
RetentionPolicy.SOURCE: 停留在java源文件,编译器被丢掉
RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认)
RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解,因此可以通过反射机制读取注解的信息
@Target元注解,默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
ElementType.CONSTRUCTOR: 构造器声明
ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
ElementType.LOCAL_VARIABLE: 局部变量声明
ElementType.METHOD: 方法声明
ElementType.PACKAGE: 包声明
ElementType.PARAMETER: 参数声明
ElementType.TYPE: 类、接口(包括注解类型)或enum声明
@Documented将注解包含在JavaDoc中
@Inheried允许子类继承父类中的注解
*/
@Target(ElementType.FIELD) //用在属性上
@Retention(RetentionPolicy.RUNTIME) //生命周期为运行时,可以通过发射获取
public @interface MyTest {
FieldType type();
}
public enum FieldType {
NAME,TEL;
FieldType() {
}
}
@Data
public class DataExcel {
@MyTest(type = FieldType.NAME)
private String name;
@MyTest(type = FieldType.TEL)
private String phone;
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> aClass = DataExcel.class;
Field[] fields = aClass.getDeclaredFields();
DataExcel dataExcel = new DataExcel();
for (int i = 0; i < fields.length; i++) {
MyTest annotation = fields[i].getAnnotation(MyTest.class);
if (Objects.equals(annotation.type(),FieldType.NAME)) {
dataExcel.setName("name");
}
if (Objects.equals(annotation.type(), FieldType.TEL)) {
dataExcel.setPhone("phone");
}
}
System.out.println(dataExcel);
}
}