注解
注释和注解为都是为了说明程序的,注释是为了成程序员看的,注解是为了给计算机看的。注解是JDk1.5之后的特性,可以声明在包、类、字段、方法、局部变量、方法参数等前面用于说明解释。
1、注解作用分类
- 编写文档:通过代码的标识的注解生成文档(javadoc 生成doc文档)
- 代码分析:通过代码的标识的注解进行代码分析(使用反射)
- 编译检查:通过代码的标识的注解让编译器实现基本的检查(比如@Override,检查是够重写)
2、JDK预定义的注解
注解 | 描述 |
---|---|
@Override | 检查被该注解标注的方法是否是继承自父类,或者接口 |
@Deprecated | 该注解标注的内容,表示已经过时 |
@SuppressWarnings | 压制警告 |
3、自定义注解
格式:
元注解
public @interface 注解名称{
属性列表
}
注解的本质:注解本质上就是一个接口,该接口继承了java.lang.annotation.Annotation接口
public interface MyAnno extends java.lang.annotation.Annotation{}
注解的属性
由于注解本质上就是一个接口,接口中可以定义抽象方法,注解的属性就是注解中的抽象方法
-
属性的返回值类型:基本数据类型、String、枚举、注解、或者以上类型的数组
-
定义了一个属性,在使用时就必须为这个属性赋值
- 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时可以不赋值(实际上是取了默认值)
- 如果只有一个属性需要赋值,那么
@myAnno(value = 12)
可以简写为@myAnno(12)
- 数组赋值时,使用大括号
自定义注解:
public @interface MyAnno { int value1(); String value2() default "猪八戒";// 如果在使用注解时不赋值,那么就默认是“猪八戒” String[] value3(); }
使用自定义注解:
public class Demo01Anno { @MyAnno(value1 = 1, value3 = "asdf") public static void method() { } }
-
元注解:用于描述注解的注解
可以在自定义的注解前面加上元注解,主要有下面的元注解:
注解 | 描述 |
---|---|
@Target | 描述注解能够作用的位置 |
@Retention | 描述注解被保留的阶段 |
@Documented | 描述注解是否被抽取到API中 |
@Inherited | 描述注解是否被子类继承 |
- 元注解@Target的属性:只有一个属性value
- 取值为ElementType.Type:表示这个被@Target描述的注解可以作用在类上
- 取值为ElementType.METHOD:表示这个被@Target描述的注解可以作用在方法上
- 取值为ElementType.FIELD:可以这个被@Target描述的注解作用在成员变量上
- 可以取值为一个数组,包含这全部三个取值,那么就可以都作用与类,方法,成员变量
- 元注解@Retention的属性:只有一个属性赋值,一般取值为RetentionPolicy.RUNTIME
- 表示当前被描述的注解会保留到字节码文件中,并被JVM读取到
- 元注解@Documented表示这个注解可以被抽取到回被抽取到API文档中
- 元注解@Inherited:表示这个被描述的注解可以被子类继承
4、使用(解析)注解
5、注解的一个使用案例
需求:现在需要测试一个类的一些方法是否有异常,如果方法有异常,就记录到一个文件中,使用注解可以来实现。
- 创建一个要测试的类的对象
- 获得这个对象的Class对象
- 获得所有的方法
- 判断该方法是否有注解@Cheak()
- 有,就执行
- 执行的时候try catch,有异常就捕获,并记录到文件中
要测试的类:目测应该有两个异常
package cn.zhuobo.annotation;
public class Calculator {
@Check
public void add() {
System.out.println("1 + 0 = " + (1 + 0));
}
@Check
public void sub() {
String s = null;
String s1 = s.toString();
System.out.println("1 - 0 = " + (1 - 0));
}
@Check
public void mul() {
System.out.println("1 * 0 = " + (1 * 0));
}
@Check
public void div() {
System.out.println("1 / 0 = " + (1 / 0));
}
}
实现的过程
package cn.zhuobo.annotation;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
/*
当主方法执行后,会检测类的所有方法,并且执行加了@Check注解的的方法,如果有异常,那么写入文件
*/
public class TestCheck {
public static void main(String[] args) throws IOException {
Calculator calculator = new Calculator();
//获得所有的方法
Class aClass = calculator.getClass();
Method[] methods = aClass.getMethods();
int count = 0;// 记录出现异常的次数
FileWriter fw = new FileWriter("bug.txt");
for (Method method : methods) {
//对于每一个method,如果有check这个注解
if(method.isAnnotationPresent(Check.class)) {
//那么就执行
try{
method.invoke(calculator);
}catch (Exception e) {
// 如果有异常,那么就在这里记录到文件,也就是异常我是这么处理的
fw.write(method.getName() + "方法出异常了
");
fw.write("异常的名称:" + e.getCause().getClass().getSimpleName() + "
");
fw.write("异常的原因:" + e.getCause().getMessage() + "
");
count++;
fw.write("================================================
");
}
}
}
fw.write("本次一共出现" + count + "次异常
");
fw.close();
}
}