注解、反射、文件IO流的综合应用

  • 准备一个简单的注解
    package com.yusian.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
    * 创建一个简单的注解SACheck
    * 该注解只能应用在方法上
    * 注解保留到运行时
    * 没有属性,只做标记用
    */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SACheck {
    }
    
  • 准备一个简单的测试类
    package com.yusian.annotation;
    
    import org.junit.Assert;
    
    /**
    * 计算器类,几个简单的方法做演示
    */
    public class Calculator {
    
      @SACheck
      public void add() {
          int ret = add(1, 2);
          String str = null;
          str.toLowerCase();  // 人为制造bug,检测测试效果
          Assert.assertEquals(3, ret);
      }
    
      @SACheck
      public void sub() {
          int ret = sub(2, 1);
          ret = 1 / 0;    // 人为制造bug,检测测试效果
          Assert.assertEquals(1, ret);
      }
    
      @SACheck
      public void multiply() {
          int ret = multiply(2, 3);
          // 人为制造bug,检测测试效果
          Assert.assertEquals(5, ret);
      }
    
      public void show() {
          System.out.println("show...");
      }
    
      public int add(int a, int b) {
          return a + b;
      }
    
      public int sub(int a, int b) {
          return a - b;
      }
    
      public int multiply(int a, int b) {
          return a * b;
      }
    
      public int divide(int a, int b) {
          return a / b;
      }
    }
    
  • 通过反射机制及注解的标记测试带SACheck注解的方法,将测试结果写入本地文件
    package com.yusian.annotation;
    
    import java.io.*;
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class AnnoDemo {
      public static void main(String[] args) throws IOException{
          // 通过Calculator类对象获取所有的成员方法
          Calculator c = new Calculator();
          Method[] declaredMethods = c.getClass().getDeclaredMethods();
    
          // bug计数,这里本来可以定义一个int变量然后++就行了,但Lambda表达式中不支持修改外部变量
          AtomicInteger errNum = new AtomicInteger();
          // 准备一个IO写入流,检测出来的bug写入到文件中
          BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
          // 使用流进行筛选与遍历,将带有@SACheck注解的方法执行并检测出是否异常,如果有则写入到文件
          Arrays.stream(declaredMethods).filter(method -> {
              return method.getAnnotation(SACheck.class) != null;
          }).forEach(method -> {
              try {
                  method.invoke(c);
              } catch (Exception e) {
                  try {
                      bw.write("错误类型:" + e.getCause().getClass().getSimpleName());
                      bw.newLine();
                      bw.write("错误原因:" + e.getCause().getMessage());
                      bw.newLine();
                      bw.write("-------------------");
                      bw.newLine();
                      errNum.getAndIncrement();
                  } catch (IOException ioException) {
                      ioException.printStackTrace();
                  }
              }
          });
          bw.write("共检测出" + errNum + "个bug");
          bw.newLine();
          bw.flush();
          bw.close();
      }
    }
    
  • 输出文件:bug.txt
    错误类型:NullPointerException
    错误原因:null
    -
    错误类型:AssertionError
    错误原因:expected:<5> but was:<6>
    -
    错误类型:ArithmeticException
    错误原因:/ by zero
    -
    共检测出3个bug
    

Leave a Reply