https://b23.tv/av62102209/p7
测试方法是否报错的框架:
扫描CC.class所在文件夹下(不递归)所有.class文件,获取文件名,再和CC的包名拼接成类名,用Class.forName加载该类。然后用反射和注解进行判断,执行带B注解的类的所有方法,记录会报错的方法。
package com.example.ee;
@B
public class A {
private Integer f1(Integer a,String b) { //int
return 1 / 0;
}
private int f2() throws Exception {
throw new Exception("what a1");
}
public String f3() {
return "oka1";
}
void f4(){
Integer a=null;
a.equals(1);
}
}
package com.example.ee;
import java.lang.annotation.*;
/**
* bbb
* @author slq
* @since 1.6
* @version 1.0
* */
//@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface B {
String q() default "";
String w() default "";
}
package com.example.ee;
import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class CC {
public static void main(String[] args) throws Exception {
testClasses();
}
public static void testClasses() throws Exception {
StringBuilder sb=new StringBuilder();
String packageName=CC.class.getPackage().getName();
String classpath = CC.class.getResource("").getPath();
File[] files = new File(classpath).listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().contains(".class");
}
});
for(File f:files){
sb=testAClass(sb,packageName+"."+f.getName().replace(".class",""));
}
System.out.println(sb.toString());
}
/**
*@param s 类名
*/
public static StringBuilder testAClass(StringBuilder sb,String s) throws Exception {
Class c=Class.forName(s);
//if(c.getAnnotation(B.class)==null){
if(!c.isAnnotationPresent(B.class)){
return sb;
}
sb.append("---------->"+s+"\n");
Object o;
try{
o=c.getDeclaredConstructor().newInstance();
}catch (Exception e){
e.printStackTrace(); //随便处理一下
return sb;
}
Method[] ms = o.getClass().getDeclaredMethods();
for(Method m:ms){
m.setAccessible(true); //使用private属性或方法需要setAccessible(true)
try{
Parameter[] parameters = m.getParameters();
Object[] objs=new Object[parameters.length];
for(int i=0;i<parameters.length;i++){
String pn=parameters[i].getType().getName();
/*方法可能要参数,而且参数的类型和个数都不定。
这里根据getParameters获得参数的类型和个数,生成一个数组应付。
不过只应付参数类型的构造方法可以是单个String的类型,如果Integer,String之类的。*/
objs[i]=Class.forName(pn).getConstructor(String.class).newInstance("1");
}
m.invoke(o,objs);
}catch (InvocationTargetException e){
String em=e.getTargetException().getMessage(); //看源码查到message在target里
//String em=e.getCause().getMessage();
/*java有一个异常链,一个异常可能是由于另一个异常引起的。
采用反射机制,我们捕捉到的异常是java.lang.reflect.InvocationTargetException,
这个异常是我们的方法所抛出的异常引起的,它的message为null。
要获取方法真正的异常,应该用e.getCause() */
sb.append(m.getName()).append("\t").append(em).append("\n");
}catch (Exception e){
e.printStackTrace(); //随便处理一下
}
}
return sb;
}
}
输出:
gggg //这两行是某个类的静态代码块
iii
---------->com.example.ee.A
f1 / by zero
f2 what a1
f4 null