JavaWeb 复习打卡day01: 2026年3月8日
目录
[一: Junit 单元测试](#一: Junit 单元测试)
[1. 测试分类](#1. 测试分类)
[2. Junit 使用步骤](#2. Junit 使用步骤)
[二: Java代码在计算机中经历的三个阶段](#二: Java代码在计算机中经历的三个阶段)
[3.1 获取字节码文件Class对象的三种方法](#3.1 获取字节码文件Class对象的三种方法)
[3.2 Class对象功能](#3.2 Class对象功能)
[3.3 反射案例](#3.3 反射案例)
一: Junit 单元测试
1. 测试分类
- 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值
- 白盒测试:需要写代码。关注程序具体的流程
2. Junit 使用步骤
(Junit 属于白盒测试)
(1).定义一个测试类(测试用例)
建议:测试类名为:被测试类名Test 如 CalculateTest
包名:xxx.xxx.xx.test 如 cn.itcast.test
(2) 定义测试方法:可以单独运行
建议:
*方法名:test测试的方法名 eg:testAdd()
*返回值:void
*参数列表:空参
(3) 给方法上面加上@Test
(4) 导入junit环境依赖
判定结果:
*❌红色:失败
*✅绿色:成功
*一般使用断言Assert来处理结果
即:Assert.assertEquals(期望的结果,运算的结果);
*补充:
@Before:修饰的方法会在测试方法之前被自动执行
@After:修饰的方法会在测试方法之后自动执行


二: Java代码在计算机中经历的三个阶段
-
Source源代码阶段------Java源代码(.java)被编译成.class文件,放置在Java虚拟机(JVM)
-
Class类对象阶段------Java虚拟机使用类加载器(ClassLoader)装载.class文件,将其加载进内存。
-
Runtime运行阶段------类加载完成之后,会进行字节码校验(这里就存在一个字节码校验器),校验通过之后,JVM解释器会把字节码翻译成机器码交由操作系统执行。

知识点
类加载器:将.class字节码文件加载进内存
Class类:用来描述所有字节码文件的共同的一些特征和行为
Class类对象有哪些呢?
-
成员变量(用来拿到值,设置值)封装为Field对象
-
构造方法(用来创建对象)封装为Constructor对象
-
成员方法(用来执行它)封装为Method对象
故,Field对象、Constructor对象、Method对象这三个对象组成了Class类。
三:反射
(反射是框架设计的灵魂)
框架: 半成本软件,可以在框架的基础上进行软件开发,简化编码
反射机制:将类的各部分封装为其他对象
好处:可以在程序运行过程中,操作这些对象;
可以解耦,提高程序的可扩展性
3.1 获取字节码文件Class对象的三种方法
- Class.formate("全类名"):将字节码文件加载进内存,返回Class对象。
使用阶段:第一阶段,当Java代码还未加载进内存时,使用该方法
使用场景:多用于配置文件,将类名定义在配置文件中,读取文件,加载类
- 类名.class:通过Class类类名的属性class获取
使用阶段:第二阶段,当字节码文件已经加载进了内存,这时有了Class对象,使用该方法
使用场景:多用于参数的传递
- 对象.getClass():该方法有在Object类中定义着
使用阶段:有对象的情况下,使用该方法
使用场景: 多用于对象获取字节码的方式
java
package com.yinyao.domain;
public class Person {
private String name;
private int age;
public String a;
public int b;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", a='" + a + '\'' +
", b=" + b +
'}';
}
public void eat(){
System.out.println("在干饭中...");
}
public void eat(String food){
System.out.println("正在吃" + food);
}
}

总结
同一个字节码文件.class 在一次程序运行过程中,只会被加载一次,不论通过哪一种方法获取的Class 对象都是同一个。
3.2 Class对象功能
(1)获取成员变量们
- Field[] getFields(): 获取所有public修饰的成员变量
- Field getField(String name):获取指定public修饰的成员变量
- Field[] getDeclaredFields(): 获取所有成员变量的值,不考虑修饰符
- Field getDeclaredField(String name): 获取指定成员变量的值,不考虑修饰符
Field成员变量对象操作
- void set(Object obj,Object value): 获取值
- get(Object obj): 设置值
- setAccessible(true):暴力反射忽略访问权限修饰符的安全检查(暴力反射)
java
package com.yinyao.reflect;
import com.yinyao.domain.Person;
import java.lang.reflect.Field;
/**
* 1. 获取成员变量们:
* *Field[] getFields():获取所有public修饰的成员变量
* *Field getField(String name):获取指定public修饰的成员变量
*
* *Field[] getDeclaredFields():获取所有成员变量的值,不考虑修饰符
* *Field getDeclaredField(String name):获取指定成员变量的值,不考虑修饰符
*/
public class ReflectDemo2 {
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
//0、获取Person的Class对象
Class personClass = Person.class;
//1.获取public修饰的成员对象们
Field[] fields = personClass.getFields();
//2.遍历public修饰的成员对象们(快捷键iter)
for (Field field : fields) {
System.out.println(field);//public java.lang.String com.yinyao.domain.Person.a
//public int com.yinyao.domain.Person.b
}
//1.获取指定成员变量a
Field a = personClass.getField("a");//getField()对其抛出异常
//2.获取成员变量a的值
Person person = new Person();//get()方法里面传入的是Person的一个对象
Object o = a.get(person);
System.out.println(o);//因为没有对其进行设置,所以默认是null
//3.设置a的值
a.set(person,"张三");
System.out.println(person);//Person{name='null', age=0, a='张三', b=0}
System.out.println(a);//public java.lang.String com.yinyao.domain.Person.a
System.out.println(person.a);//张三
//1.获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
//2.遍历
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
/**
* 遍历后得:
* private java.lang.String com.yinyao.domain.Person.name
* private int com.yinyao.domain.Person.age
* public java.lang.String com.yinyao.domain.Person.a
* public int com.yinyao.domain.Person.b
*/
//1.获取指定成员变量的值,不考虑修饰符
Field age = personClass.getDeclaredField("age");
System.out.println(age);//private int com.yinyao.domain.Person.age
//2.获取age的值
//2.1进行忽略访问权限修饰符的安全检查
age.setAccessible(true);//暴力反射
//2.2利用get方法获取
Person person1 = new Person();
Object o1 = age.get(person1);
System.out.println(o1);//0
//3.设置age的值
age.set(person1,21);
System.out.println(person1.getAge());//21
}
}
(2)获取构造方法们
- Constructor<?>[] getConstructors():获取所有public修饰的构造方法
- Constructor<T>[] getConstructor(类<?>...parameterTypes):获取指定参数的公共构造方法
- Constructor<?>[] getDeclaredConstructors():获取类中所有构造方法(不分权限)
- Constructor<T>[] getDeclaredConstructor(类<?>...parameterTypes):获取指定参数的任意权限构造方法
Constructor构造方法对象操作
- T newInstance(Object... initargs): 创建对象,如果使用空参构造方法创建对象,操作可以简化,即使用Class对象的 newInstance() 方法
- setAccessible(true): 忽略访问权限修饰符的安全检查(暴力反射)
java
package com.yinyao.reflect;
import com.yinyao.domain.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
*2. 获取构造方法们:
* *Constructor<?>[] getConstructors():获取所有public修饰的构造方法
* *Constructor<T>[] getConstructor(类<?>...parameterTypes)
*
* *Constructor<?>[] getDeclaredConstructors()
* *Constructor<T>[] getDeclaredConstructor(类<?>...parameterTypes)
*/
public class ReflectDemo3 {
public static void main(String[] args) throws NoSuchMethodException,
InvocationTargetException, InstantiationException, IllegalAccessException {
//0、获取Person的Class对象
Class<Person> personClass = Person.class;
//1.获取构造方法对象
Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);//抛出异常
System.out.println(constructor);//public com.yinyao.domain.Person(java.lang.String,int)
//2.根据构造方法创建对象
Person person = constructor.newInstance("张三", 23);//抛出异常
System.out.println(person);//Person{name='张三', age=23, a='null', b=0}
System.out.println("--------------------------------------------------------");
//创建空参对象(不需要创建构造方法对象)
Person person1 = personClass.newInstance();
System.out.println(person1);//Person{name='null', age=0, a='null', b=0}
}
}
(3)获取成员方法们
- Method[] getMethods():自身 + 父类的所有 public 方法
- Method getMethod(String name,类<?>...parameterTypes):自身 + 父类的指定 public 方法
- Method[] getDeclaredMethods():仅自身的所有方法(任意权限)
- Method getDeclaredMethod(String name,类<?>...parameterTypes):仅自身的所有方法(任意权限)
Method 构造方法对象操作
- Object invoke(Object obj,Object... args): 执行方法
- String getName : 获取执行方法名称
java
package com.yinyao.reflect;
import com.yinyao.domain.Person;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 3. 获取成员方法们:
* *Method[] getMethods()
* *Method getMethod(String name,类<?>...parameterTypes)
*
* *Method[] getDeclaredMethods()
* *Method getDeclaredMethod(String name,类<?>...parameterTypes)
*
* 4. 获取类名:
* *String getName()
*/
public class ReflectDemo4 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//0、获取Person的Class对象
Class personClass = Person.class;
//1.获取指定public修饰的成员方法(空参方法)
Method eat_method = personClass.getMethod("eat");//抛出异常
Person person = new Person();
//2.执行方法
eat_method.invoke(person);//在干饭中... 抛出异常
System.out.println("--------------------------------------------");
//1.获取指定public修饰的成员方法(带参数)
Method eat_method1 = personClass.getMethod("eat", String.class);
Person person1 = new Person();
//2.执行方法
eat_method1.invoke(person1,"糖醋鱼");//正在吃糖醋鱼
System.out.println("---------------------------------------------");
//获取全部public修饰的方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);//因为Person类继承Object类,所以打印出来后还会有一些隐藏的Object类里的方法
String methodName = method.getName();//获取方法名称
System.out.println(methodName);
}
System.out.println("************************************************");
String className = personClass.getName();
System.out.println(className);//com.yinyao.domain.Person
}
}
3.3 反射案例
-
需求:案例:写一个"框架",不能改变任何代码的前提下, 可以帮我们创建任意类的对象,并且执行其中任意方法。
-
实现:配置文件 + 反射技术
-
步骤:
-
将需要创建的对象的全类名和需要执行的方法定义在配置文件中
-
在程序代码中加载读取配置文件
-
使用反射技术来加载类文件进内存
-
创建对象
-
执行方法

java
package com.yinyao.reflect;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* 案例:写一个"框架",
* 不能改变任何代码的前提下,
* 可以帮我们创建任意类的对象,并且执行其中任意方法
*/
public class ReflectDemo5 {
public static void main(String[] args) throws IOException, ClassNotFoundException,
InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//1.加载配置文件
//1.1创建Properties对象
Properties properties = new Properties();
//1.2加载配置文件,转换为一个集合
//1.2.1获取class目录下的配置文件
ClassLoader classLoader = ReflectDemo4.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");//getResourceAsStream获取资源对应的字节流
properties.load(resourceAsStream);
//2.获取配置文件中定义的数据
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
//3.加载该类进内存
Class aClass = Class.forName(className);//抛出异常
//4.创建对象
Object o = aClass.newInstance();//抛出异常
//5.获取成员方法对象
Method method = aClass.getMethod(methodName);//抛出异常
//6.执行方法
method.invoke(o);//抛出异常
}
}
