1、junit的使用
junit单元测试
测试分类:
1、黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值
2、白盒测试:需要写代码,关注程序具体的执行流程
junit其实就是白盒测试的一种
使用步骤:
1、定义一个测试类
package com.itheima.junit;
//定义一个计算器类
public class Calculator {
//加法运算方法
public int add(int a,int b){
return a + b;
}
//减法运算方法
public int sub(int a,int b){
return a - b;
}
}
2、定义测试方法:可以独立运行
package com.itheima.test;
import com.itheima.junit.Calculator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.security.PublicKey;
public class CalculatorTest {
/**
* 初始化方法:
* 用于资源申请,所有测试方法在执行前都会先执行该方法
*/
@Before
public void init(){
System.out.println("init...");
}
/**
* 释放资源方法
* 在所有测试方法执行完之后,都会自动执行该方法
*/
@After
public void close(){
System.out.println("close...");
}
@Test
public void testadd(){
Calculator calculator = new Calculator();
int result = calculator.add(1, 2);
Assert.assertEquals(3,result);
}
@Test
public void testsub(){
Calculator calculator = new Calculator();
int result = calculator.sub(1,1);
Assert.assertEquals(0,result);
}
}
3、给测试方法加上@Test注解
4导入junit依赖环境
判定结果:
红色:失败
绿色:成功
一般我们会使用断言操作来处理结果
Assert.assertEquals(期望的结果,运算的结果);
补充:
@Before:
修饰的方法会在测试方法执行之前被自动运行
@After
修饰的方法会在测试方法执行之后被自动运行
2、反射
反射被称为框架设计的灵魂
框架:半成品软件,可以在框架的基础上进行软件开发,简化编码
反射:将类的各个组成部分封装为其他对象,这就是反射机制
好处:
1、可以在程序运行过程中,操作这些对象
2、可以解耦,提高程序的可扩展性
获取Class对象的方式:
1、Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
多用于配置文件,将类定义在配置文件中,读取文件,加载类
2、类名.Class:通过类名的属性class获取
多用于参数的传递
3、对象.getClass():getClass()方法在object类中定义着
多用于对象的获取字节码的方式
package com.itheima.reflect;
import com.itheima.domain.Person;
public class ReflectDemo1 {
/**
* 1、Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
*
* 2、类名.Class:通过类名的属性class获取
*
* 3、对象.getClass():getClass()方法在object类中定义着
*
*/
public static void main(String[] args) throws Exception {
//1、Class.forName(“全类名”)
Class cls1 = Class.forName("com.itheima.domain.Person");
System.out.println(cls1);
//2、类名.Class
Class cls2 = Person.class;
System.out.println(cls2);
//3、对象.getClass()
Person person = new Person();
Class cls3 = person.getClass();
System.out.println(cls3);
}
}
结论:
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪种方式获取的class对象都是同一个。
Class对象功能:
获取功能:
1、获取成员变量们
Field[ ] getFields() 获取所有public修饰的成员变量
Field geiField(String name) 获取指定名称的public修饰的成员变量
Field[ ] getDeclareFields()
Field getDeclareField(String name)
Field:成员变量
操作:
1、设置值 get()
2、获取值 set()
3、忽略访问权限修饰符的安全检查
setAccessible(true):暴力反射
package com.itheima.reflect;
import com.itheima.domain.Person;
import java.lang.reflect.Field;
public class ReflectDemoField {
/**
* Class对象功能:
* 获取功能:
* 1、获取成员变量们
* Field[ ] getFields()
* Field geiField(String name)
*
* Field[ ] getDeclareFields()
* Field getDeclareField(String name)
*/
public static void main(String[] args) throws Exception {
//获取Person的class对象
Class personClass = Person.class;
//1、 Field[ ] getFields() 获取所有public修饰的成员变量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("--------------------");
//2、Field geiField(String name) 获取指定名称的public修饰的成员变量
Field a = personClass.getField("a");
//获取成员变量a的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
//设置a的值
a.set(p,"张三");
System.out.println(p);
System.out.println("=================================");
//3、Field[ ] getDeclareFields() 获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("--------------------");
//4、Field getDeclareField(String name) 获取指定名称成员变量,不考虑修饰符
Field d = personClass.getDeclaredField("d");
//忽略访问权限修饰符的安全检查
d.setAccessible(true); //暴力反射
Object value2 = d.get(p);
System.out.println(value2);
}
}
2、获取构造方法们
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor<?>[] getDeclaredClasses()
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
Constructor:构造方法
创建对象:
T newInstance(Object... initargs)
如果使用空参数构造方法创建对象,操作可以简化:class对象的newInstance方法
忽略访问权限修饰符的安全检查
setAccessible(true):暴力反射
package com.itheima.reflect;
import com.itheima.domain.Person;
import java.lang.reflect.Constructor;
public class ReflectDemoConstructor {
/*
2、获取构造方法们
* Constructor<?>[] getConstructors()
* Constructor<T> getConstructor(类<?>... parameterTypes)
*
* Constructor<?>[] getDeclaredClasses()
* Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
*/
public static void main(String[] args) throws Exception {
//获取Person的class对象
Class personClass = Person.class;
//1、Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor constructor = personClass.getConstructor(String.class, int.class);
System.out.println(constructor);
//创建对象
Object person = constructor.newInstance("张三", 23);
System.out.println(person);
System.out.println("===============");
//如果使用空参数构造方法创建对象,操作可以简化:class对象的newInstance方法
Object o = constructor.newInstance();
System.out.println(o);
}
}
3、获取成员方法们
Method[ ] getMethods();
Method getMethod(String name,类<?>... parameterTypes
)
Method[ ] getDeclareMethods();
Method getDeclareMethod(String name,类<?>... parameterTypes
)
Method:方法对象
执行方法:
Object invoke(Object obj,Object... args)
获取方法的名称:
String getName:获取方法名
4、获取类名
String getName()
package com.itheima.reflect;
import com.itheima.domain.Person;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemoMethod {
/*
3、获取成员方法们
* Method[ ] getMethods();
* Method getMethod(String name,类<?>... parameterTypes)
*
* Method[ ] getDeclareMethods();
* Method getDeclareMethod(String name,类<?>... parameterTypes)
*/
public static void main(String[] args) throws Exception {
//获取Person的class对象
Class personClass = Person.class;
//Method[ ] getMethods(); 获取指定名称的成员方法
Method eat = personClass.getMethod("eat");
Person p = new Person();
//执行方法
eat.invoke(p);
System.out.println("=====================");
Method eat1 = personClass.getMethod("eat", String.class);
eat1.invoke(p,"饭");
System.out.println("=====================");
//获取所以public修饰的方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
String name = method.getName();
System.out.println(name);
// method.setAccessible(true);
System.out.println("======================");
//获取类名
String classname = personClass.getName();
System.out.println(classname);
}
}
}
案例:
需求:写一个“框架”,不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且之前其中任意的方法
实现:
1、配置文件
2、反射
步骤:
1、将需要创建的全类名和需要执行的方法定义在配置文件中
例如:我拥有一个person类和一个student类
package com.itheima.domain;
public class Person {
public void eat(){
System.out.println("eat...");
}
}
package com.itheima.domain;
public class Student {
public void sleep(){
System.out.println("sleep...");
}
}
里面有eat方法和sleep方法
创建pro.properties配置文件并且将类的全类名和方法写入
className=com.itheima.domain.Student
methodName=sleep
2、在程序中加载读取配置文件
//1、加载配置文件
//1.1创建properties对象
Properties properties = new Properties();
//1.2、加载配置文件,转换为一个集合
//获取class目录下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
properties.load(resourceAsStream);
//2、获取配置文件中定义的数据
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
3、使用反射技术来加载类文件进内存
//3、加载该类进内存
Class cls = Class.forName(className);
4、创建对象
//创建对象
Object obj = cls.newInstance();
5、执行方法
//获取方法对象
Method method = cls.getMethod(methodName);
//执行方法
method.invoke(obj);