1.什么是注解
1.1概念
说明程序的,给计算机看的。
什么是注释:用文字描述程序的,给程序员看的。
百度上的解释:
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制,是一种代码级别的说明。Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。
概念描述:
- JDK1.5 之后的新特性
- 用来说明程序的
- 使用注解:@注解名称
1.2 作用分类
- 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
- 编写文档:通过代码里标识的注解生成文档【生成文档doc文档】,API文档是通过抽取代码中的文档注释生成的。
例如新建一个类:
打开命令行窗口,用 javadoc AnnoDemo1.java 这个命令进行抽取,点开生成文件中的index.html:
\3. 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
2. JDK中预定义的一些注解
@Override : 检测被该注解标注的方法是否搜集继承自父类(接口)的
@Deprecated :将该注解标注的内容,表示已过时
@SuppressWarnings :压制警告,一般传递参数all @SuppressWarnings(“all”)
3. 自定义注解
3.1 格式
元注解: public @interface 注解名称{}
3.2 注解的本质
注解本质上就是一个接口,该接口默认继承Annotation接口
将以下注解编译过后进行反编译,得到结果:
编译前:
1 | public interface MyAnno{ |
反编译后:
1 | public interface MyAnno extends java.lang.annotation.Annotation{ |
3.3 属性
可以理解为接口中可以定义的抽象方法。
要求:
1.属性的返回值类型只能为以下几种:
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
2.定义了的属性(本质上是抽象方法),在使用时需要进行赋值
- 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
- 如果只有一个属性需要赋值,并且这个属性的名称是value,那么value可以省略,直接赋值即可。
- 数组赋值时,值使用大括号包裹。如果数组中只有一个值,那么{}可以省略
3.4 元注解
概念:用于描述注解的注解。
@Target:描述能够作用的位置
1 | //表示该MyAnno注解只能作用于类上 (value = {ElementType.TYPE}) |
其中value中ElementType取值可以有以下几种情况:
- TYPE:可以作用在类上
- METHOD:可以作用在方法上
- FIELD:可以作用于成员变量上
1 | (value = {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD}) |
@Retention:描述注解被保留的阶段
@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到字节码文件中,并被JVM读取到,一般自己定义的注解都加RUNTIME
@Documented:描述该注解是否会被抽取到api文档中
@Inherited:描述注解是否被子类继承
4. 在程序中使用注解
注解在程序中经常和反射一起使用,注解大多数来说都是用来替换配置文件的,拿之前反射的程序来举例:
被测试的类AnnoTest1:
1 | public class AnnoTest1 { |
原始的反射代码:
1 | package cn.other.reflect; |
对应的配置文件pro:
1 | className=cn.other.annotation.AnnoTest1 |
新建注解AnnoReflect :
1 | package cn.other.annotation; |
使用注解的方式来淘汰配置文件(注释很重要):
1 | package cn.other.annotation; |
运行结果:
使用总结:
在程序中使用注解:获取注解中定义的属性值
- 获取注解定义的位置的对象 (Class, Method, Field)
- 获取指定的注解:getAnnotation(Class)
- 调用注解中的抽象方法获取配置的属性值
案例:简单的测试框架
需求:设计一个框架,检测一个类中的方法使用有异常,并进行统计。
待测试的类
1 | package cn.other.annotation.demo; |
如何实现
首先自定义一个注解:
1 | //运行时 (RetentionPolicy.RUNTIME) |
然后编写一个类专门用于检查(注意注释):
1 | package cn.other.annotation.demo; |
在待测试的类中每个需要测试的方法前面都加上@Check
1 | package cn.other.annotation.demo; |
运行TestCheck类中的主方法,就会自动检查所有注解@Check的方法是否异常:
小结 :
- 大多数时候,我们会使用注解而不是自定义注解
- 注解给编译器和解析程序用
- 注解不是程序的一部分,可以理解为标签