单元测试
就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。
咱们之前是如何进行单元测试的?有啥问题 ?
Junit单元测试框架
可以用来对方法进行测试,它是由Junit公司开源出来的
具体步骤
Junit框架的常见注解
public class StringUtilTest {@Test@Beforepublic void testPrintNumber(){StringUtil.printNumber("哈哈");StringUtil.printNumber(null);}@Testpublic void testGetMaxIndex(){int sum = new StringUtil().getMaxIndex("蝙蝠侠不打你了");System.out.println(sum);Assert.assertEquals("警告,警告",6,sum);}@Test@Afterpublic void testPrint(){System.err.println("结束");}
}
反射(Reflection)
反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。
反射学什么?
获取Class对象的三种方式
1.直接使用类名.class获取:Class c1 = 类名.class
2.调用Class提供的方法:Class c2 = Class.forName("全类名")
3.调用Object提供的方法:Class c3 = 对象.getClass()
public class Demo1 {@Testpublic void testDemo01() throws ClassNotFoundException {Class catClass = Cat.class;System.out.println(catClass.getName());Class aClass = Class.forName("com.itheima.b_反射.Cat");System.out.println(aClass);Class aClass1 = new Cat().getClass();System.out.println(aClass1);}
}
获取类的构造器
/*
获取构造器[下面是Class的方法]Constructor<?>[] getConstructors() 获取所有的公共构造器(只能获取public修饰的)Constructor<?>[] getDeclaredConstructors() 获取全部构造器(只要存在就能拿到)Constructor<T> getConstructor(Class<?>... parameterTypes) 获取某个公共构造器(只能获取public修饰的)Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取某个构造器(只要存在就能拿到)使用构造器(创建对象)[下面是Constructor的方法]T newInstance(Object... initArgs) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)注意使如果想使用private修饰构造器反射创建对象,需要暴力反射(禁止JVM检查构造方法的访问权限)
*/
public class Demo2 {@Testpublic void testConstructor() throws NoSuchMethodException {Class<Cat> clazz = Cat.class;//获取全部构造器(public)Constructor[] constructors = clazz.getConstructors();for (Constructor constructor : constructors) {System.out.println(constructor);}Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);}System.out.println("====================================");Constructor<Cat> constructor = clazz.getConstructor();System.out.println(constructor);System.out.println("===============================");Constructor<Cat> declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);System.out.println("方法名:" + declaredConstructor.getName() + "参数个数:"+ declaredConstructor.getParameterCount());}@Testpublic void testNew() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class calazz = Cat.class;Constructor declaredConstructor = calazz.getDeclaredConstructor(String.class, int.class);declaredConstructor.setAccessible(true);Cat 加菲猫 = (Cat)declaredConstructor.newInstance("加菲猫", 3);System.out.println(加菲猫);}
}
获取类的成员变量
public class Demo3 {@Testpublic void testField() throws NoSuchFieldException {Class<Cat> catClass = Cat.class;//获取类的所有公共成员变量(只能获取public修饰的)Field[] fields = catClass.getFields();for (Field field : fields) {System.out.println(field);}System.out.println("===============");//获取类的全部成员变量Field[] declaredFields = catClass.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println(declaredField.getName() + declaredField.getType());}System.out.println("====================");Field a = catClass.getField("a");//获取某个类的成员变量,只要存在就能拿到System.out.println(a);Field age = catClass.getDeclaredField("age");System.out.println(age);}@Testpublic void test2() throws NoSuchFieldException, IllegalAccessException {Class clazz = Cat.class;Cat cat = new Cat();// System.out.println(cat);Field age = clazz.getDeclaredField("age");Field name = clazz.getDeclaredField("name");//暴力反射age.setAccessible(true);name.setAccessible(true);age.set(cat,5);name.set(cat,"哈哈");System.out.println(cat);//取值Object o = age.get(cat);System.out.println(o);}
}
获取类的成员方法
/*
获取成员方法[Class提供]Method[] getMethods() 获取类的全部公共成员方法(只能获取public修饰的)Method[] getDeclaredMethods() 获取类的全部成员方法(只要存在就能拿到)Method getMethod(String name, Class<?>... parameterTypes) 获取类的某个公共成员方法(只能获取public修饰的)Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取类的某个成员方法(只要存在就能拿到)使用成员方法(执行方法)[Method提供]public Object invoke(Object obj, Object... args) 触发某个对象的该方法执行。public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)注意使如果想使用private修饰的成员方法,需要暴力反射
*/
public class Demo4 {@Testpublic void testMethods() throws NoSuchMethodException {Class<Cat> catClass = Cat.class;Method[] methods = catClass.getMethods();for (Method method : methods) {System.out.println("方法名:"+ method.getName() + "返回值类型:" + method.getReturnType());}System.out.println("===========================");Method[] declaredMethods = catClass.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println("方法名:"+ declaredMethod.getName() + "返回值类型" + declaredMethod.getReturnType());}System.out.println("===========================");Method eat = catClass.getDeclaredMethod("eat");System.out.println("方法名:"+ eat.getName() + "返回值类型" + eat.getReturnType());System.out.println("===========================");Method eat1 = catClass.getDeclaredMethod("eat", String.class);System.out.println("方法名:"+ eat1.getName() + "返回值类型" + eat1.getReturnType());}@Testpublic void tese2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {Class<Cat> clazz = Cat.class;Method eat = clazz.getDeclaredMethod("eat", String.class);eat.setAccessible(true);Cat cat = new Cat();Object invoke = eat.invoke(cat, "🐟");System.out.println(invoke);}
}
案例:
/*
反射案例对于任意一个对象,该框架都可以把对象的字段名和对应的值,然后打印在控制台*/
public class Demo5 {public static void main(String[] args) {//1. 准备两个对象Student student = new Student("柳岩", 40, '女', 167.5, "女星");Teacher teacher = new Teacher("播妞", 6000);//2.调用方法print(student);}public static void print(Object o) {try {Class clazz = o.getClass();Field[] declaredFields = clazz.getDeclaredFields();for (Field declaredField : declaredFields) {declaredField.setAccessible(true);String name = declaredField.getName();Object o1 = declaredField.get(o);System.out.println(name+o1);}}catch (Exception e){}}
}class Student{public Student(String name, int age, char sex, double height, String hobby) {this.name = name;this.age = age;this.sex = sex;this.height = height;this.hobby = hobby;}private String name;private int age;private char sex;private double height;private String hobby;
}class Teacher {public Teacher(String name, double salary) {this.name = name;this.salary = salary;}private String name;private double salary;
}
反射的作用
注解
元注解
指的是:修饰注解的注解。
注解解析器
就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。
如何解析注解
public class ClassNameCheckParser {public static void checkClassName(){//1.存放不符合规范的类ArrayList<String> list = new ArrayList<>();//2.获取指定包下的所有类Set<Class> clazzSet = ClassUtil.getClasses("com.itheima.c_annotation.example");//3.遍历set集合找到标注@ClassNameCheck注解的类'for (Class clazz : clazzSet) {//判断某个类上是否有某个注解if(clazz.isAnnotationPresent(ClassNameCheck.class)){//获得类名String simpleName = clazz.getSimpleName();//检查类名是否以Heima开头if(!simpleName.startsWith("Hei")){list.add(simpleName);}}}//判断集合中是否有不符合规范的,如果有直接保存if(list.size() > 0) {System.out.println("下面类名不符合规范");for (String name : list) {System.out.println(name);}throw new RuntimeException("程序终止");}}}