单元测试
就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。
咱们之前是如何进行单元测试的?有啥问题 ?
Junit单元测试框架
可以用来对方法进行测试,它是由Junit公司开源出来的
具体步骤
Junit框架的常见注解
public class StringUtilTest {
@Test
@Before
public void testPrintNumber(){
StringUtil.printNumber("哈哈");
StringUtil.printNumber(null);
}
@Test
public void testGetMaxIndex(){
int sum = new StringUtil().getMaxIndex("蝙蝠侠不打你了");
System.out.println(sum);
Assert.assertEquals("警告,警告",6,sum);
}
@Test
@After
public 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 {
@Test
public 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 {
@Test
public 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());
}
@Test
public 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 {
@Test
public 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);
}
@Test
public 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 {
@Test
public 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());
}
@Test
public 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("程序终止");
}
}
}