Java之Junit和反射
Posted 我想回家
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java之Junit和反射相关的知识,希望对你有一定的参考价值。
Junit,反射
Junit
1.测试的分类:
- 黑盒测试 : 不需要写代码,给输入值,看程序是否能够输出期望的值。
- 白盒测试 : 需要进行代码的编写,关注的是程序的具体流程.
2.使用步骤(方法类的命名可以参考阿里巴巴开发手册):
* 步骤:
1. 定义一个测试类(测试用例)
* 建议:
* 测试类名:被测试的类名Test
* 包名:xxx.xxx.xx.test
2. 定义测试方法:可以独立运行
* 建议:
* 方法名:test测试的方法名 testAdd()
* 返回值:void
* 参数列表:空参
3. 给方法加@Test
4. 导入junit依赖环境
* 判定结果:
* 红色:失败
* 绿色:成功
* 一般我们会使用断言操作来处理结果
* Assert.assertEquals(期望的结果,运算的结果);
* 补充:
* @Before:
* 修饰的方法会在测试方法之前被自动执行
* @After:
* 修饰的方法会在测试方法执行之后自动被执行
// 举个例子
public class Calculator {
/**
* 加法运算
* @param a 加数
* @param b 被加数
* @return 和
*/
public int add(int a,int b){
return a + b;
}
/**
* 减法运算
* @param a 减数
* @param b 被减数
* @return 差值
*/
public int sub(int a,int b){
return a - b;
}
}
// 测试类的创建
package com.wzlove.test;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* @author 王智
* @date 2018/7/31
* @描述 测试类
*/
public class CalculatorTest {
Calculator cal;
/**
* 初始化
*/
@Before
public void init(){
// 初始化对象
cal = new Calculator();
System.out.println("init==================================================");
}
/**
* 测试加法运算
*/
@Test
public void testAdd(){
// 调用方法
int result = cal.add(10, 10);
// 断言
Assert.assertEquals(20,result);
}
/**
* 测试减法运算
*/
@Test
public void testSub(){
// 调用方法
int result = cal.sub(10, 10);
// 断言
Assert.assertEquals(0,result);
}
@After
public void end(){
System.out.printf("end========================================");
}
}
反射 : 框架的设计灵魂
- 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
- 反射:将类的各个组成部分封装为其他对象,这就是反射机制
- 好处:
- 可以在程序运行过程中,操作这些对象。
- 可以解耦,提高程序的可扩展性。
- 好处:
- 获取Class对象的方式:
- Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
- 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
- 类名.class:通过类名的属性class获取
- 多用于参数的传递
- 对象.getClass():getClass()方法在Object类中定义着。
- 多用于对象的获取字节码的方式
- 结论:
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
package com.wzlove.reflect;
/** * @author 王智 * @date 2018/7/31 * @描述 获取字节码对象的三种方式 */ public class GetClassObject { public static void main(String[] args) throws Exception { // 第一种: 使用全类名进行获取 Class<?> aClass = Class.forName("com.wzlove.reflect.GetClassObject"); System.out.println(aClass); // 第二种: 使用类名的属性获取 Class aClass1 = GetClassObject.class; System.out.println(aClass1); // 第三种: 使用类的方法进行获取 Class<?> aClass2 = new GetClassObject().getClass(); System.out.println(aClass2); System.out.println(aClass == aClass1); System.out.println(aClass == aClass2); } }
- Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
- Class对象功能:
获取功能:
- 获取成员变量们
- Field[] getFields() :获取所有public修饰的成员变量
Field getField(String name) 获取指定名称的 public修饰的成员变量
- Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
- Field getDeclaredField(String name)
- 获取构造方法们
- Constructor<?>[] getConstructors()
Constructor
- Constructor
- Constructor<?>[] getDeclaredConstructors()
- Constructor<?>[] getConstructors()
- 获取成员方法们:
- Method[] getMethods()
Method getMethod(String name, Class<?>... parameterTypes)
- Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
- Method[] getMethods()
- 获取全类名
- String getName()
- 获取成员变量们
- Field:成员变量
- 操作:
- 设置值
- void set(Object obj, Object value)
- void set(Object obj, Object value)
- 获取值
- get(Object obj)
- 忽略访问权限修饰符的安全检查
- setAccessible(true):暴力反射
- 设置值
// 下面的例子全部使用Student类
package com.wzlove.reflect;/** * @author 王智 * @date 2018/7/31 * @描述 */ public class Student { private String name; private int age; public String sex; @Override public String toString() { return "Student{" + "name=‘" + name + ‘‘‘ + ", age=" + age + ", sex=‘" + sex + ‘‘‘ + ‘}‘; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Student(String name, int age, String sex) { this.name = name; this.age = age; this.sex = sex; } public Student() { } } package com.wzlove.reflect; import java.lang.reflect.Field; /** * @author 王智 * @date 2018/7/31 * @描述 利用反射获取对象的成员变量 */ public class GetFieldDemo { public static void main(String[] args) throws Exception { // 利用反射获取公有成员变量的步骤 // 1. 获取反射对象(3种方法) Class aClass = Student.class; // 2. 获取成员变量 Field sex = aClass.getField("sex"); // 3. 使用Field的方法设置值(需要创建对象) Student stu = new Student(); sex.set(stu,"男"); // 4. 使用Field的方法获取值 System.out.println(sex.get(stu)); // 获取所有成员变量 // 1. 获取反射对象(3种方法) Class aClass1 = Student.class; // 2. 获取成员变量 Field name = aClass1.getDeclaredField("name"); // 3. 使用Field的方法设置值(需要创建对象) Student stu1 = new Student(); // 4. 再使用私有变量的时候会报错,所以要跳过检测,也成为暴力反射 name.setAccessible(true); name.set(stu1,"王智"); // 6. 使用Field的方法获取值 System.out.println(name.get(stu1)); } }
- 操作:
- Constructor:构造方法
- 创建对象:
T newInstance(Object... initargs)
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
package com.wzlove.reflect;
import java.lang.reflect.Constructor; /** * @author * @date 2018/7/31 * @描述 利用反射获取对象的构造方法 */ public class GetConstructDemo { public static void main(String[] args) throws Exception { // 利用反射获取公有成员变量的步骤 // 1. 获取反射对象(3种方法) Class aClass = Student.class; // 2. 使用方法获取构造方法的对象 Constructor constructor = aClass.getConstructor(String.class, int.class, String.class); // 3. 使用Constructor对象初始化对象 Object obj = constructor.newInstance("张三", 23, "男"); // 测试输出结果 System.out.println(obj); System.out.println("==================================="); // 无参构造的方法 // 1. 获取反射对象(3种方法) Class aClass1 = Student.class; // 2. 使用方法获取构造方法的对象 Constructor constructor1 = aClass1.getConstructor(); // 3. 使用Constructor初始化对象 Object obj1 = constructor1.newInstance(); // 测试输出结果 System.out.println(obj1); // 还有个简化写法,仅仅适用于无参构造,但是我使用JDK10已经不推荐使用了 Object obj2 = aClass1.newInstance(); System.out.println(obj2); // getDeclaredConstructor方法也是获取私有的构造方法,就不演示了 } }
- 创建对象:
- Method:方法对象
- 执行方法:
- Object invoke(Object obj, Object... args)
- 获取方法名称:
- String getName:获取方法名
- 执行方法:
首先在Student中添加两个方法
public void eat(){
System.out.println("eat..............");
}
public int add(int a, int b){
return a + b;
}
package com.wzlove.reflect;
import java.lang.reflect.Method;
/**
* @author 王智
* @date 2018/7/31
* @描述 反射执行方法
*/
public class GetMethodDemo {
public static void main(String[] args) throws Exception {
// 无参无返回值的方法
// 1. 创建字节码对象
Class aClass = Student.class;
// 2. 创建方法的对象
Method eat = aClass.getMethod("eat");
// 3. 执行方法
Student stu = new Student();
eat.invoke(stu);
// 有参有返回值的方法
// 1. 创建字节码对象
Class aClass1 = Student.class;
// 2. 创建方法的对象
Method add = aClass1.getMethod("add", int.class,int.class);
// 3. 执行方法
Student stu1 = new Student();
Object sum = add.invoke(stu1, 10, 10);
System.out.println("和为" + sum);
System.out.println("======================================================");
// 获取该类所有的方法(这里获取的不仅仅是自己定义的方法,还有从父类继承来的方法)
Method[] methods = aClass1.getMethods();
for (Method method : methods) {
System.out.println(method);
System.out.println(method.getName());
}
System.out.println("======================================================");
// 获取类名
System.out.println(aClass1.getName());
// getDeclaredMethod也是同样的道理
}
}
以上就是反射的简单使用了.举个简单例子,当然这个例子并不完善,将就看
package com.wzlove.reflect;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @author
* @date 2018/7/31
* @描述
* * 案例:
* * 需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,
* 并且执行其中任意方法
* * 实现:
* 1. 配置文件
* 2. 反射
* * 步骤:
* 1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
* 2. 在程序中加载读取配置文件
* 3. 使用反射技术来加载类文件进内存
* 4. 创建对象
* 5. 执行方法
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 创建本类的字节码对象
Class aClass = ReflectDemo.class;
// 获取类加载器对象
ClassLoader classLoader = aClass.getClassLoader();
// 加载配置文件,返回字节流对象
InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
// 读取配置文件
// 创建Properties对象
Properties properties = new Properties();
properties.load(resourceAsStream);
// 反射的使用
Object className = properties.getProperty("className");
Object methodName = properties.getProperty("methodName");
// 使用反射创建对象
Class aClass1 = Class.forName((String) className);
Constructor constructor = aClass1.getConstructor();
Object obj = constructor.newInstance();
// 利用反射获取方法
Method method = aClass1.getMethod((String) methodName);
// 使用反射执行方法
method.invoke(obj);
}
}
以上是关于Java之Junit和反射的主要内容,如果未能解决你的问题,请参考以下文章