注解是JDK1.5后的新特性。
JDK预定义注解:
- @Override(检测被注解的方法是否继承自父类)
- @Deprecated(将被注解标记为已过时)
- @SuppressWarnings(镇压警告,参数一般为all)
自定义注解:
-
定义格式
public @interface MyAnno { }
-
本质,将编译后的class文件使用javap反编译得到
public interface MyAnno extends java.lang.annotation.Annotation{ }
所以,注解的本质就是接口!
注解的属性:
-
属性的返回值类型限定为:
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
-
因为注解的本质是接口,在注解中定义的属性也就是方法,使用时给不同属性赋值可以看做为给方法一个返回值(格式:属性名=值)。
-
当注解只有一个属性,且属性名为value时,使用注解赋值时可以直接赋值;
-
定义注解时,可以使用default关键字设置默认值,没有设置默认值的属性使用时必须赋值;
public @interface MyAnno { String name() default "zh"; }
-
属性的赋值实例
@MyAnno(value = 1,per=Person.P1,anno2 = @MyAnno2,strs = {"aa","bb"}) public class Worker { }
元注解:
- 用于描述注解的注解
- @Target:注解作用的位置
- @Retention:注解保留的阶段
- @Documented:注解是否被抽取到api文档中
- @Inherited:注解是否被子类继承
注解的解析使用:
-
使用注解定义类名和方法名,然后执行
//定义的注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Pro { String className(); String methodName(); } //解析注解 @Pro(className = "com.package.Demo",methodName = "show") public class Example { public static void main(String[] args) throws Exception { // 解析注解,获取当前的Class Class exampleClass = Example.class; // 获取上边的注解 // 实际就是在内存中生成了一个该注解接口的子类实现对象 Pro annotation = (Pro) exampleClass.getAnnotation(Pro.class); // 调用注解的方法获取设置的属性 String className=annotation.className(); String methodName=annotation.methodName(); System.out.println(className); System.out.println(methodName); // 获取到className后实例化Class对象 Class aClass = Class.forName(className); // 利用Class对象获取方法 Method method = aClass.getMethod(methodName); // 利用Class对象生成一个实例 Object obj=aClass.newInstance(); // 执行方法 method.invoke(obj); } }
通过注解测试方法:
-
注解定义
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Check { }
-
需要测试的类和方法
public class Calculator { @Check public void add(){ System.out.println("1+0="+(1+0)); } @Check public void sub(){ 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)); } public void show(){ System.out.println("show"); } }
-
实现代码
public class TestChek { public static void main(String[] args) throws IOException { // 创建计算器对象 Calculator calculator=new Calculator(); // 获取字节码文件对象 Class c=calculator.getClass(); // 获取所有方法 Method[] methods=c.getMethods(); // 判断方法是否又check注解 // 有就执行 int num=0;//出现异常的次数 BufferedWriter bw=new BufferedWriter(new FileWriter("bug.txt")); for (Method method : methods) { if(method.isAnnotationPresent(Check.class)){ try { method.invoke(calculator); } catch (Exception e) { num++; bw.write(method.getName()+"方法出异常了"); bw.newLine(); bw.write("异常的名称:"+e.getCause().getClass().getSimpleName()); bw.newLine(); bw.write("异常的原因:"+e.getCause().getMessage()); bw.newLine(); bw.write("-----------------"); bw.newLine(); // e.printStackTrace(); } } } bw.write("一共"+num+"次异常"); // 捕获异常 bw.flush(); bw.close(); } }