说明:本次课程学习了 反射机制(Reflection)(Demo04:反射概念、普通调用 vs 反射调用、为什么需要反射、反射核心类)、获取 Class 对象三种方式(Demo05:类名.class / 对象.getClass() / Class.forName("全类名"),同一个类三种方式拿到同一个对象)、反射 Constructor 构造方法(Demo06:getConstructors / getConstructor / getDeclaredConstructors / getDeclaredConstructor 获取构造方法、setAccessible(true) 暴力反射、newInstance() 反射创建对象、instanceof 判断 + 强转调用方法)。
本作业共 1 道题(必做):用反射分别通过 SysUser 的 4 个构造方法(public 无参 / private 二参 / public 六参 / private 四参)创建对象——覆盖"拿 Class → 拿构造 → 建对象"的反射创建对象完整流程,重点练习 getDeclaredConstructor + setAccessible(true) 暴力反射访问私有构造方法。
| 项目 | 要求 |
|---|---|
| 类名 | Demo_01_你的姓名(如 Demo_01_张三) |
| 文件头注释 | Java 文件头部需包含 @author、@title、@create 文档注释 |
| 实体类 | 使用课程代码中的 course.SysUser 实体类(授课代码/c260812/src/course/SysUser.java) |
| 项目 | 要求 |
|---|---|
| 提交方式 | 将源码文件 + 运行结果截图提交至班级指定平台 |
| 截止时间 | 下次上课前 |
知识点:获取 Class 对象三种方式(类名.class / 对象.getClass() / Class.forName("全类名"),同一个类三种方式拿到同一个对象)、getConstructors() / getDeclaredConstructors() 获取构造方法数组、getConstructor(参数类型...) / getDeclaredConstructor(参数类型...) 获取指定构造方法、newInstance() 反射创建对象、setAccessible(true) 暴力反射访问私有构造、instanceof 判断类型、向下转型、调用 toString()
场景描述:课堂学了反射最核心的用途——拿到 Class 对象后,通过构造方法创建对象(这是 Spring IOC 等框架的底层原理)。SysUser 系统用户类一共有 4 个构造方法(2 个 public + 2 个 private):
// SysUser 的 4 个构造方法(源码:course/SysUser.java)
public SysUser() // ① public 无参
private SysUser(String username, String password) // ② private 二参(用户名,密码)
public SysUser(String id, String username, String password,
String name, String phone, String email) // ③ public 六参(完整用户信息)
private SysUser(String id, String name,
String phone, String email) // ④ private 四参(基础信息)
请用反射分别通过这 4 个构造方法创建 4 个 SysUser 对象——完整走一遍"拿 Class → 拿构造 → 建对象"的反射创建对象流程,并重点体会:private 构造方法必须用 getDeclaredConstructor + setAccessible(true) 暴力反射才能调用。
💡 获取 Class 对象的方式:第一步"拿 Class"有三种方式任选其一,结果殊途同归(同一个类三种方式拿到的是同一个对象)—— ①
SysUser.class(类名.class,编译期类型检查最安全) ②new SysUser().getClass()(对象.getClass(),需先有对象实例) ③Class.forName("course.SysUser")(全类名字符串,最灵活、框架最常用)
题目要求:
/**
* @author 你的姓名
* @title 题目1:反射遍历 SysUser 四个构造方法创建对象
* @create 2026/8/12
*/
实现步骤:
SysUser.class / new SysUser().getClass() / Class.forName("course.SysUser"))getConstructors() 统计 public 构造个数(2 个),getDeclaredConstructors() 统计全部构造个数(4 个,含 private)getConstructor() 获取 public 无参构造 → newInstance() 创建空对象getConstructor(String.class × 6) 获取 public 六参构造 → newInstance(id, username, password, name, phone, email) 创建完整用户对象getDeclaredConstructor(String.class, String.class) 获取 private 二参构造 → setAccessible(true) → newInstance("admin", "admin888") 暴力反射创建对象getDeclaredConstructor(String.class × 4) 获取 private 四参构造 → setAccessible(true) → newInstance(id, name, phone, email) 暴力反射创建对象instanceof SysUser 判断 + 打印 toString() 验证属性代码框架:
package course;
import java.lang.reflect.Constructor;
public class Demo_01_你的姓名 {
public static void main(String[] args) throws Exception {
// 1. 获取 SysUser 的 Class 对象(类.class / 对象.getClass() / Class.forName 三选一)
// 2. 分别打印 public 构造个数和全部构造个数
// 3. 用 public 无参构造反射创建对象①,并 instanceof 判断
// 4. 用 public 六参构造反射创建对象②
// 5. 用 private 二参构造反射创建对象③(需放开访问权限)
// 6. 用 private 四参构造反射创建对象④(需放开访问权限)
}
}
输出示例:
public 构造方法个数:2
全部构造方法个数(含private):4
① 无参构造:SysUser{id='null', username='null', password='null', name='null', phone='null', email='null'}(是SysUser吗?true)
② 六参构造:SysUser{id='1', username='zhangsan', password='123456', name='张三', phone='13800000000', email='zhangsan@qq.com'}
③ 私有二参构造:SysUser{id='null', username='admin', password='admin888', name='null', phone='null', email='null'}
④ 私有四参构造:SysUser{id='2', username='null', password='null', name='李四', phone='13900000000', email='lisi@qq.com'}
选做加分:
setAccessible(true) 注释掉再运行,观察抛 IllegalAccessException——体会"私有构造必须放开访问权限"getConstructor(String.class, String.class)(不带 Declared)尝试获取 private 二参构造,观察抛 NoSuchMethodException——验证"不含 Declared 只能拿 public"for (Constructor<?> c : clazz.getDeclaredConstructors()) 打印每个构造的 getParameterCount()(参数个数)和 getParameterTypes()(参数类型),观察 4 个构造的参数差异SysUser.class / new SysUser().getClass() / Class.forName("course.SysUser")),打印三个对象是否相等(== 结果应为 true)思考题(将答案写在代码文件头注释或提交报告里):
getConstructor() 拿不到它们?必须用什么方法组合?(提示:getDeclaredConstructor + setAccessible(true),口诀"含 Declared 的才能拿私有")setAccessible(true) 做了什么?Object 类型,怎么确认它确实是 SysUser?确认后如何调用 SysUser 的方法?(提示:instanceof + 强转)类名.class / 对象.getClass() / Class.forName)有什么区别?哪种最灵活、框架最常用?(提示:类名.class 编译期类型检查最安全 / getClass() 需先有对象实例 / Class.forName 字符串传类名最灵活,是框架最常用的方式)| 知识点 | 说明 |
|---|---|
Class.forName("全类名") |
方式三获取 Class 对象:字符串传类名、最灵活、框架最常用;全类名写错抛 ClassNotFoundException |
| 获取 Class 对象三种方式 | ①类名.class(编译期类型检查最安全)②对象.getClass()(需有对象实例)③Class.forName(最灵活)——同一个类三种方式拿到同一个对象 |
getConstructors() / getDeclaredConstructors() |
分别获取 public 构造数组 / 全部构造数组(含 private)——SysUser 对应 2 个和 4 个 |
getConstructor() / newInstance() |
获取 public 无参构造 + 反射创建对象(对应普通 new 类名()) |
getConstructor(参数类型...) |
获取指定参数类型的 public 构造方法,newInstance(参数...) 创建带属性对象 |
getDeclaredConstructor(参数类型...) |
获取指定参数类型的构造方法(含 private),需配合 setAccessible(true) |
setAccessible(true) 暴力反射 |
放开私有成员的访问权限,否则调用 private 构造的 newInstance() 会抛 IllegalAccessException |
newInstance() |
反射创建对象;public 构造直接调用,private 构造需先 setAccessible(true) |
| instanceof + 向下转型 | 反射创建的对象是 Object 类型,instanceof SysUser 判断后强转再调用方法 |
| 反射 API 的受检异常 | ClassNotFoundException / NoSuchMethodException / InstantiationException / IllegalAccessException / InvocationTargetException——必须处理(main 用 throws) |