第1章 Junit 单元测试
Junit 介绍为了对某个方法进行更快捷地测试,我们需要学习Junit 技术。
JUnit 是一个Java 语言的单元测试框架,简单理解为可以用于取代 java 的 main 方法。Junit 属于第三方工具,一般情况下需要导入 jar 包,不过,多数 Java 开发环境已经集成了JUnit 作为单元测试工具。
效果:
@Test 修饰的要求:必须 public、无 static、无参、无返回值
Junit-进阶案例凡是加入@符号的,Java 中我们都称为注解。常用注解
@Test, 修饰需要被执行的测试方法
@Before,修饰的方法无法独立执行,必须在 测试方法执行之前先执行@After, 修饰的方法无法独立执行,必须在 测试方法执行之后再执行被以上三个注解修饰的的方法:必须 public、无 static、无参、无返回值
public class JunitDemo_1 { @Test
public void myTest(){ System.out.println("测试 test");
}
@Before
public void myBefore(){ System.out.println("方法前");
}
@After
public void myAfter(){ System.out.println("方法后");
}
/*运行结果:
*/
}
执行类中全部测试方法:
常见错误:
第2章 反射【重点】
学习前准备学习前准备---知识储备为了能够更加灵活地访问类中的所有内容(包含 private),我们就需要反射技术
通过反射技术,我们可以轻松访问图中类的 private 内容。
反射:针对性地映射 某一个完整事物的行为或特征 (单独操作类中任意内容 的超能力)
Java 反射机制是在运行状态中:
把类中任意部分作为对象获取到:
学习访问权限时,我们就知道,private 修饰的方法,仅限当前类内部使用。
我们可以通过反射技术,在不修改访问权限修饰符的前提下,在外界使用 private 方法。
public class Person {
private void t1(){
System.out.println("私有的 t1 方法执行");
}
private void t2(){
System.out.println("私有的 t2 方法执行");
}
}
定义一个测试类,测试类中执行 Person 类中的 t1 方法。
因为Person 类中的 t1 方法是 private 修饰,正常创建对象方式无法调用方法。只能依靠反射技术
public static void main(String[] args) throws Exception {
//1、获取
//1.1、获取类对象
Class<?> clazz = Class.forName("com.czxy.demo2.d1.Person");
//1.2、获取类中方法
Method t1 = clazz.getDeclaredMethod("t1");
//1.3、(private)设置类外可用-暴力反射
t1.setAccessible(true);
//2、执行
//2.1、获取类中构造方法
Constructor<?> c = clazz.getConstructor();
//2.2、根据构造方法创建对象
Object person = c.newInstance();
//2.3、调用方法
t1.invoke(person);
}
获取全类名的两种方式:
反射执行 private 方法步骤:
1、获取
2、执行
思考:
控制台输入方法名:t1 或 t2,输入的方法名是什么,就执行 Person 中的哪个方法。如果输入的方法不存在,展示“方法不存在”
}
}
System.out.println("整数:" b);
public class Person {
private void t1(){
System.out.println("私有的 t1 方法执行");
}
private void t2(){
System.out.println("私有的 t2 方法执行");
}
private void t3(String a,int b){
System.out.println("字符串:" a);
定义一个测试类,测试类中执行Person 类中的 t3 方法,方法传入“传智” 1024
private 方法仍然是使用反射技术调用,但在获取方法和执行方法上要注意有方法参数
public static void main(String[] args) throws Exception {
//1、获取
//1.1、获取类对象
Class<?> clazz = Class.forName("com.czxy.demo2.d1.Person");
//1.2、获取类中方法(告诉程序,t3 方法有 String 和 int 两个参数)
Method t3 = clazz.getDeclaredMethod("t3", String.class, int.class);
//1.3、设置类外可用
t3.setAccessible(true);
//2、执行
//2.1、获取类中构造方法
Constructor<?> c = clazz.getConstructor();
//2.2、根据构造方法创建对象
Object person = c.newInstance();
//2.3、调用方法(分别为 String 和 int 赋值)
t3.invoke(person,"传智",1024);
}
反射执行带参方法,获取和执行时都要注意参数
public class Person {
private void t1(){
System.out.println("私有的 t1 方法执行");
}
private void t2(){
System.out.println("私有的 t2 方法执行");
}
private void t3(String a,int b){
System.out.println("字符串:" a);
System.out.println("整数:" b);
}
private String t4(){
return "t4 方法的返回值";
}
}
定义一个测试类,测试类中执行Person 类中的 t4 方法,展示方法返回值
private 方法仍然是使用反射技术调用,执行方法完毕,接收返回值即可
public static void main(String[] args) throws Exception {
//1、获取
//1.1、获取类对象
Class<?> clazz = Class.forName("com.czxy.demo2.d1.Person");
//1.2、获取类中方法
Method t3 = clazz.getDeclaredMethod("t4");
//1.3、设置类外可用
t3.setAccessible(true);
//2、执行
//2.1、获取类中构造方法
Constructor<?> c = clazz.getConstructor();
//2.2、根据构造方法创建对象
Object person = c.newInstance();
//2.3、调用方法(接收返回值)
Object x = t3.invoke(person);
String str = (String) x;
System.out.println(str);
}
反射调用方法的返回值是 Object 类型,可以通过强转 转为具体使用格式(强转前一定确定,方法返回值真正是什么类型,否则类型不匹配报异常)
反射方式调用方法,可以让我们使用类中任何方法(包括 private) 格式:
反射执行 private 方法步骤:(即使 2.1 和 2.2 紧跟在 1.1 之后,也是一种编写方式)
1、获取
2、执行
public class Phone { public void start(){
System.out.println("开机");
}
}
@Test
public void run() throws Exception {
//1、获取类的 Class 对象
Class<?> clazz = Class.forName("cn.czxy.demo2.Phone");
//2 、 通 过 Constructor 实 例 化 对 象 Constructor<?> c1 = clazz.getConstructor(); Object obj = c1.newInstance();
//3、获取 Method 对象
Method m1 = clazz.getMethod("start");
//4、执行方法m1.invoke(obj);
}
1、
getMethod(); 获取当前类或父类中的 public 修饰的方法
getDeclaredMethod(); 获取当前类中任意的方法(无视访问权限)
2、若使用 getMethod();方法尝试获取非 public 修饰的方法,会出现如下异常:
3、反射 private 方法 必须使用 setAccessible(true),否则将抛异常:
进阶 2:强制执行 private 字段@Test
public void run3() throws Exception{
//1、获取 Class 对象
Class<?> c1 = Class.forName("cn.czxy.demo5.People");
//2、通过构造方法创建对象(链式编程)
Object obj = c1.getConstructor().newInstance();
//3、获取 Field 对象
Field idNum = c1.getDeclaredField("idNum");
//设置该方法在外界暂时可用idNum.setAccessible(true);
//4、赋值/取值idNum.set(obj, "666666");
Object idNumStr = idNum.get(obj); System.out.println(idNumStr);
}
public class Person {
public String name="小智";
}
@Test
public void run1() throws Exception{
//1、获得 类的“Class 对象”
Class<?> clazz = Class.forName("cn.czxy.demo3.Person");
//2 、 通 过 Constructor 实 例 化 对 象 Constructor<?> c1 = clazz.getConstructor(); Object obj = c1.newInstance();
//3、获取 Field 对象
Field f1 = clazz.getField("name");
//4、赋值/取值
Object str = f1.get(obj); System.out.println(str); f1.set(obj, "小明");
}
注意:
1、getField(); 只能获取当前类或父类中 public 修饰的字段
getDeclaredField (); 获取当前类中的任意字段(无视访问权限修饰符)
2、若使用 getField ();方法尝试获取非 public 修饰的字段,会出现如下异常:
3、反射 private 字段 必须使用 setAccessible(true),否则将抛异常:
进阶 4:通过私有构造创建对象(private 修饰)public class Person { private Person() {
System.out.println("私有无参构造");
}
}
@Test
public void run1() throws Exception{
//1、获取 Class 对象
Class<?> c1 = Class.forName("cn.czxy.demo5.Person");
//2 、 获 取 非 公 有 构 造 方 法 ( 不 是 public) Constructor<?> c = c1.getDeclaredConstructor();
//设置该构造方法在外界暂时可用
c.setAccessible(true);
//使用私有构造创建对象
Object obj = c.newInstance();
}
public class Phone {
//普通方法
public void call(String num){ System.out.println("打电话给:" num);
}
public String shutDown(){ return "关机成功";
}
//构造方法
public Phone() { System.out.println("Phone 无参构造");
}
public Phone(String a,int b) { System.out.println("Phone 带参构造" a b);
}
}
@Test
public void run5() throws Exception{
//1、获取 Class 对象
Class<?> clazz = Class.forName("cn.czxy.demo4.Phone");
//2、通过带参构造创建对象
Constructor<?> c = clazz.getConstructor(String.class,int.class);
Object obj = c.newInstance("你好",10);
}
1、getConstructor(); 只能获取当前类中,public 修饰的任意构造方法
getDeclaredConstructor(); 获取当前类中任何构造方法(无视访问权限修饰符)
2、若使用 getConstructor();方法尝试获取非 public 修饰的构造方法,会出现如下异常:
3、反射 private 构造方法 必须使用 setAccessible(true),否则将抛异常:
反射高级案例获取所有方法&获取所有字段&所有构造方法getMethods(); 获取当前类及父类中所有的 public 修饰的方法
getDeclaredMethods(); 获取当前类中所有的方法(无视访问权限)
getFields(); 获取当前类及父类中所有的 public 修饰的字段
getDeclaredFields (); 获取当前类中的所有字段(无视访问权限修饰符)
getConstructors(); 获取当前类中所有的 public 修饰的构造方法
getDeclaredConstructors(); 获取当前类中所有构造方法(无视访问权限修饰符)
总结:
所有未加 Declared 的方法,都能获取当前类及父类所有 public 内容所有加 Declared 的方法,都能获取当前类所有内容
高级 2:获取类的 Class 对象的三种方式@Test
public void run1() throws Exception{
//1、通过 Class.forName()方法
Class c1 = Class.forName("cn.czxy.demo4.Phone");
//2、类名.class
Class c2 = Phone.class;
//3、对象名.getClass()方法Phone p1 = new Phone(); Class c3 = p1.getClass();
}
注意:以上三种方式获取的某个类的 Class 对象都是同一个
任何 class 文件使用时,都会成为内存中的一个 Class 对象
public class Person {
//家里的小金库
private double deposit;
//从家里小金库里取出 1 千
private double withDraw(){ double money = 1000.0;
// 尝 试 取 1000 deposit-=money; if(deposit<0){
//若小金库不足 1000,无法取出deposit =money;
return 0.0;
}
return money;
}
}
@Test
public void run1() throws Exception{ Person p1 = new Person();
//请补全代码,完成以下操作
//1、为对象 p1 的成员变量 deposit 赋值 20 万
//2、使用对象 p1 的 withDraw()方法,取出 5000
}
要求:
1、 Person.java 的源代码不可改变
2、 补全代码:为对象 p1 的成员变量 deposit 赋值 20 万
3、 补全代码:使用对象 p1 的 withDraw()方法,取出 5000
提示:
Person 对象 p1 已经存在,就无需反射构造方法创建对象了, 直接使用 p1 对象即可
综合练习:寻找某些指定方法执行【扩展,仅供学有余力同学自学】public class DemoTest {
public void run1(){System.out.println("run1");} void run2(){System.out.println("run2");}
private void run3(){System.out.println("run3");}
void test1(){System.out.println("test1");} void test2(){System.out.println("test2");}
public void test3(){System.out.println("test3");}
protected void run1es(){System.out.println("run1es");} void run2es(){System.out.println("run2es");}
private void run3es(){System.out.println("run3es");}
}
要求:
1、执行所有以“run”开头的方法。(方法无参、无返回值)
2、执行以“es”结尾的方法,要求方法必须以 public 修饰。(方法无参、无返回值)
若找不到,则展示“没有 es 结尾的方法”
提示:
1、获取方法的名字: method 对象.getName(); 2、获取多个 method 的方法:
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved