文章目录
Junit单元测试
测试分类
黑盒测试
:不需要写代码,给输入值,看程序是否能够输出期望的值。白盒测试
:需要写代码的。关注程序具体的执行流程。
Junit使用:白盒测试
例如想测试一个已经写好的类 以往的方法是创建一个mian类然后new一个对象调用方法进行测试
有了单元测试就不用main方法可以运行自己写的方法
public class Calculator { //计算类
public int add(int a, int b) { //加法
return a + b;
}
public int sub(int a, int b) { //减法
return a - b;
}
}
要想测试上述的方法首先创建一个测试类CalculatorTest类 通常都是需要测试的类后面加Test
类创建成功后添加一个给方法添加一个注解@Test
package day_1;
import org.junit.Assert;
import org.junit.Test;
public class CalculatorTest {
@Test
public void addTest() {
Calculator calculator = new Calculator();
int result = calculator.add(10, 10);
Assert.assertEquals(20, result); //
}
@Test
public void subTest() {
Calculator calculator = new Calculator();
int result = calculator.sub(20, 10);
Assert.assertEquals(19, result);
}
}
Assert是一个断言类 调用assertEquals()方法可以处理结果
通常测试类都应该放在自己定的Test包中
Java反射
什么是框架?
框架是相当于一个半成品软件,可以在框架的基础上进行软件的开发,从而简化代码
什么是反射?
反射是框架设计的灵魂,在运行时去获取一个类的变量和方法信息,然后通过获取到的信息来创建对象,调用方法的一种机制
也就是将类的各个组成部分封装成其他对象
反射有什么好处?
- 可以再程序运行过程中操作这些对象,也就是不停止程序创建对象
- 可以解耦,提高程序的可扩展性
怎样获取Class对象?
获取Class对象有三种方法
Class.forName("全类名")
:将字节码文件加载进内存,返回Class对象
//多用于配置文件
,将类名定义在配置文件中。读取文件,加载类类名.class
:通过类名的属性class获取
//多用于参数的传递对象.getClass()
:getClass()方法在Object类中定义着。
//多用于对象的获取字节码的方式
看看例子
public class Example_1 {
public static void main(String[] args) throws ClassNotFoundException {
//第一种方法
Class<?> student = Class.forName("Student");
//第二种方法
Class<Student> studentClass = Student.class;
//第三种方法
Student stu = new Student();
Class<? extends Student> stuClass = stu.getClass();
}
}
要注意的是同一个字节码文件(.class
)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
获取了Class对象后它有什么功能?
获得Class对象后有四种功能
1. 如何获取成员变量?
方法名 | 说明 |
---|---|
Field[] getFields() | 获取所有public修饰的成员变量 |
Field getField(String name) | 获取指定名称的 public修饰的成员变量 |
Field[] getDeclaredFields() | 获取所有的成员变量,不考虑修饰符 |
Field getDeclaredField(String name) | 获取指定名称的成员变量 |
获取了成员变量能干什么?
肯定是对成员变量进行操作啊
方法名 | 说明 |
---|---|
void set(Object obj, Object value) | 用于设置值 |
get(Object obj) | 获取值 |
既然能获取到私有变量那么能不能对它操作?
答案是可以的,那就是忽略访问权限修饰符的安全检查,这个方法称为暴力反射
方法体 | 说明 |
---|---|
setAccessible(true) | 暴力反射 |
import java.lang.reflect.Field;
public class Example_1 {
public static void main(String[] args) throws Exception {
Class student = Class.forName("day_1.Student"); //使用第一种方法
Field[] fields = student.getFields(); //获取所有public修饰的成员变量
Field subject = student.getField("subject");//获取指定名称的public修饰的成员变量
Field[] declaredFields = student.getDeclaredFields(); //获取所有成员变量,忽略修饰符
Field age = student.getDeclaredField("age"); //获取指定成员变量,忽略修饰符
for (Field f : //对获取到的所有成员变量进行遍历
declaredFields) {
System.out.println(f);
}
Student stu = new Student();
age.setAccessible(true); //暴力反射
age.set(stu, 22); //设置设置对象的私有变量
System.out.println(stu);
}
}
2. 如何获取构造方法们?
方法体 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 获取不带参数的构造方法 |
Constructor getConstructor(类<?>… parameterTypes) | 获取指定参数的构造方法 |
Constructor getDeclaredConstructor(类<?>… parameterTypes) | 获取私有的构造方法 |
Constructor<?>[] getDeclaredConstructors() | 获取指定私有的构造方法 |
获取到了构造方法然后可以干什么?
获取到了构造方法就可以进行实例化创建对象
了
方法体 | 说明 |
---|---|
T newInstance(Object… initargs) |
如果使用空参数构造方法创建对象,可以直接用类对象直接调用newInstance()方法,不过此方法已经过时
import java.lang.reflect.Constructor;
public class example_2 {
public static void main(String[] args) throws Exception {
Class student = Class.forName("day_1.Student");
Constructor constructor0 = student.getConstructor();//获取所有不带参数的构造方法
Constructor constructor = student.getConstructor(String.class,int.class); //获取指定参数的构造方法
Object o = constructor0.newInstance(); //不带参数的对象实例化
System.out.println(o);
Object o1 = constructor.newInstance("小红",20); //带参数对象实例化
System.out.println(o1);
Object o2 = student.newInstance(); //直接用类对象实例化
System.out.println(o2);
}
}
3. 如何获取成员方法们?
方法体 | 说明 |
---|---|
Method[] getMethods() | 获取所有public方法 包括object类的方法 |
Method getMethod(String name, 类<?>… parameterTypes) | 获取指定public方法 |
Method[] getDeclaredMethods() | 获取所有方法 忽略修饰 不包括object类的方法 |
Method getDeclaredMethod(String name, 类<?>… parameterTypes) | 获取指定方法 和忽略修饰 |
获取到了成员方法可以干什么?
获取到了方法就可以执行了啊
方法体 | 说明 |
---|---|
Object invoke(Object obj, Object… args) | 对象执行方法 |
String getName | 获取方法名 |
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class example_3 {
public static void main(String[] args) throws Exception {
Class studentClass = Class.forName("day_1.Student");
Constructor studentClassConstructor = studentClass.getConstructor();
Object o = studentClassConstructor.newInstance();
// Method[] methods = studentClass.getMethods(); //获取所有方法 包括了object类的方法
// for (Method m :
// methods) {
// System.out.println(m);
// }
Method[] declaredMethods = studentClass.getDeclaredMethods(); //不包括object类的方法
for (Method m :
declaredMethods) {
System.out.println(m);
}
Method setName = studentClass.getDeclaredMethod("setName", String.class); //获取指定类型的方法
setName.invoke(o,"小红"); //方法被执行
System.out.println(o);
}
}
4.如何获取类名?
用Class对象调用一个getName()方法即可
如何去写一个框架呢?
写一个框架的目就是不改变任何代码的前提下可以帮助我们创建任意类的对象 并且执行其中任意方法
怎么去实现呢?
这个时候就要用到反射和配置文件
那么如何去创建一个配置文件呢?
右击新建一个文件把后序名改为properties
有了配置文件就可以写框架了
package day_1.example;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
public class example_4 {
public static void main(String[] args) throws Exception {
//1.加载配置文件
Properties properties = new Properties(); //将后序名为properties的文件形成一个集合
//获如何获取文件的路径呢?
ClassLoader classLoader = example_4.class.getClassLoader(); //可以用类获取类加载器
//有了类加载器就可以找配置文件
InputStream resourceAsStream = classLoader.getResourceAsStream("my.properties");//获取对应资源的资源流
properties.load(resourceAsStream); //加载
//2.获取配置文件中定义的数据
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
//3.加载该类进内存
Class aClass = Class.forName(className);
//4.创建对象
Constructor constructor = aClass.getConstructor();
Object o = constructor.newInstance();
Method method = aClass.getMethod(methodName);
method.invoke(o); //方法被执行
}
}
运行结果
当修改配置文件中的study为play时(student类有两个方法 一个为study 另一个为play)
那么此时不用修改代码然后运行的结果
CET4P245
- alarm
- community
- whoever
- impress
- isolate
- semester
- snap
- hut
- wholly
- ache