自定义注解
格式
元注解
public @interface 注解名称{
属性列表;
}
Note:注解本质上就是一个接口,该接口默认继承Annotation接口。
*public interface MyAnno extends java.lang.annotation.Annotation
属性
属性:接口中的抽象方法
要求:
- 属性的返回值类型有下列取值
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
- 定义了属性,在使用时需要给属性赋值
- 如果定义属性时,使用default关键字给属性默认初始化,则使用注解可不进行属性的赋值。
- 如果只有一个属性需要赋值,并且属性的名称为value,则value可以省略,直接定义值即可。
- 数组赋值时,值使用{ }包裹,如果数组中只有一个值,则{ }可以省略。
元注解
元注解:用于描述注解的注解
- @Target:描述注解能够作用的位置
- ElementType.TYPE 可以作用于类
- ElementType.METHOD 可以作用于方法
- ElementType.FIELD 可以作用于成员变量上 - @Retention: 描述注解被保留的阶段
- RetentionPolicy.SOURCE 在源文件中有效(即源文件保留)
- RetentionPolicy.CLASS 在class文件中有效(即class保留)
- RetentionPolicy.RUNTIME 在运行时有效(即运行时保留) - @Documented : 描述注解是否被抽取到api文档中
*note:javadoc **.java 生成api文档 - @Inherited : 描述注解是否被子类继承
解析注解
- 获取注解定义的位置的对象
- 获取制定的注解
//getAnnotation(class)
//其实就是在内存中生成了一个改注解接口的子类实现对象
public class ProUmpl implements Pro{
public String className(){
return "cn.itcast.annotation.Demo1";//注解中属性className的属性值代入,实现抽象方法
}
public String methodName(){
return "show";//注解中属性methodName的属性值代入,实现抽象方法
}
}
- 调用注解中的抽象方法获取配置的属性值
以上为注解的理论知识
应用
通过使用注解,反射机制设计一个测试框架,记录出错的个数,以及出错的名称及原因。
package calculator;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
package calculator;
public class Calculator {
@Check
public void add() {
String aString = null;
aString.toString();
System.out.println("1+0="+(1+0));
}
@Check
public void sub() {
System.out.println("1-0="+(1-0));
}
@Check
public void divide() {
System.out.println("1/0="+1/0);
}
@Check
public void mul() {
System.out.println("1*0="+(1*0));
}
@Check
public void show() {
System.out.println("永无bug");
}
}
package calculator;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestCheck {
public static void main(String[] args) throws IOException {
// 创建计算器对象
Calculator c = new Calculator();
//获取字节码文件对象
Class cls = c.getClass();
//3.获取所有的方法
Method[] methods = cls.getMethods();
int number = 0;//记录出现错误的次数
BufferedWriter bWriter = new BufferedWriter(new FileWriter("bug.txt"));
for(Method method: methods) {
if(method.isAnnotationPresent(Check.class)) {
try {
method.invoke(c);
} catch (Exception e) {
number++;
bWriter.write(method.getName()+"出异常了");
bWriter.newLine();
bWriter.write("异常名称:"+e.getCause().getClass().getSimpleName());
bWriter.newLine();
bWriter.write("异常原因:"+e.getCause().getMessage());
bWriter.newLine();
bWriter.write("------------------------------------");
bWriter.newLine();
}
}
//System.out.println(method);
}
bWriter.write("本次测试一共出现"+number+"次异常");
bWriter.flush();
bWriter.close();
}
}
- 后续补充一个解析注解的案例