什么是注解
其实注解并不复杂,使用注解一定会有三个过程:定义注解,使用注解,读取注解。我们一步一步来看:
定义注解
定义没什么好说的1
2
3
4
5@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Six{
String name() default "nanwei";
}
- 使用
@interface定义注解 @Target和@Retention是元注解,就是注解的注解。。。。。,一共四种- Target表示注解的作用目标,看代码
1 | @Documented |
ElementType是一个枚举类,包括type,field,method等常见的注解目标
Retention定义注解的保留策略
1
2
3@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到,正常来说定义在运行时才能发挥大作用Document:说明该注解将被包含在javadoc中,生成java文档的时候会用到
- Inherited:说明子类可以继承父类中的该注解,这里要注意的是,仅类的注解可以被集成,接口的不行,类内的变量和方法也不行
- 定义值,关键字default表默认值,仅支持基本类型和String,不支持Object,因为注解参数是一种编译时常量,那时候还没有对象呢,这算是java的一个设计缺陷吧,不知道以后会不会改进
使用注解
使用注解就很简单了,Override什么的我们也经常用,上面我们自己定义的也一样用1
2
3
4
5
6
7
8public class Student implements Algorithm{
@Six(name="666")
public String name;
public void setName(String name){
this.name = name;
}
}
我们看到name这个类变量有一个Six注解,参数666,好了,我们新建一个Student类,打印它的名字:1
2Student student = new Student();
Utils.printString("=======>>>>1: " + student.name);
结果1
=======>>>>1: null
好像这个注解并没有起什么作用,这是因为,这个注解虽然被编译进了class文件,加载类之后也进入了运行时,但是因为我们没有做解析这个注解的操作,所以没有生效,那么怎么解析呢?使用反射,这就是解析注解这一步
解析注解
1 | public class SixProcessor { |
可以看到,上面对Student对象的所有类变量遍历,检查是否有Six注解,如果有,则把注解的参数值赋给Student的name:1
2SixProcessor.process(student);
Utils.printString("=======>>>>2: " + student.name);
结果是1
=======>>>>2: 666
注解有什么作用呢
基于上述注解的特性,注解的主要作用有:
- 编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
- 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
- 编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】