面向对象3(Junit 反射)

面向对象3(Junit 反射)

首页枪战射击反射单元2更新时间:2024-06-28

1Junit 单元测试

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

}

要求:

1Person.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