# 2026年8月12日 课后作业 — 反射:遍历 SysUser 四个构造方法创建对象 > **说明**:本次课程学习了 **反射机制(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`) | ### 二、提交方式与截止时间 | 项目 | 要求 | |------|------| | **提交方式** | 将源码文件 + 运行结果截图提交至班级指定平台 | | **截止时间** | 下次上课前 | --- ## 一、基础题(必做) ### 题目 1:反射遍历 SysUser 四个构造方法创建对象(⭐⭐⭐ 必做) **知识点**:`Class.forName("全类名")` 获取 Class 对象、`getConstructors()` / `getDeclaredConstructors()` 获取构造方法数组、`getConstructor(参数类型...)` / `getDeclaredConstructor(参数类型...)` 获取指定构造方法、`newInstance()` 反射创建对象、`setAccessible(true)` 暴力反射访问私有构造、`instanceof` 判断类型、向下转型、调用 toString() **场景描述**:课堂学了**反射最核心的用途**——拿到 Class 对象后,通过构造方法创建对象(这是 Spring IOC 等框架的底层原理)。`SysUser` 系统用户类一共有 **4 个构造方法**(2 个 public + 2 个 private): ```java // 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)` 暴力反射**才能调用。 **题目要求**: ```java /** * @author 你的姓名 * @title 题目1:反射遍历 SysUser 四个构造方法创建对象 * @create 2026/8/12 */ ``` **实现步骤**: 1. `Class.forName("course.SysUser")` 获取 SysUser 的 Class 对象 2. `getConstructors()` 统计 public 构造个数(2 个),`getDeclaredConstructors()` 统计全部构造个数(4 个,含 private) 3. **反射创建对象①**:`getConstructor()` 获取 public 无参构造 → `newInstance()` 创建空对象 4. **反射创建对象②**:`getConstructor(String.class × 6)` 获取 public 六参构造 → `newInstance(id, username, password, name, phone, email)` 创建完整用户对象 5. **反射创建对象③**:`getDeclaredConstructor(String.class, String.class)` 获取 private 二参构造 → `setAccessible(true)` → `newInstance("admin", "admin888")` 暴力反射创建对象 6. **反射创建对象④**:`getDeclaredConstructor(String.class × 4)` 获取 private 四参构造 → `setAccessible(true)` → `newInstance(id, name, phone, email)` 暴力反射创建对象 7. 每个对象 `instanceof SysUser` 判断 + 打印 `toString()` 验证属性 **代码框架**: ```java package course; import java.lang.reflect.Constructor; public class Demo_01_你的姓名 { public static void main(String[] args) throws Exception { // 1. 用 Class.forName 获取 SysUser 的 Class 对象 // 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**——体会"私有构造必须放开访问权限" - **Declared 口诀验证**:用 `getConstructor(String.class, String.class)`(不带 Declared)尝试获取 private 二参构造,观察抛 **NoSuchMethodException**——验证"不含 Declared 只能拿 public" - **遍历构造方法**:`for (Constructor c : clazz.getDeclaredConstructors())` 打印每个构造的 `getParameterCount()`(参数个数)和 `getParameterTypes()`(参数类型),观察 4 个构造的参数差异 - 分别用三种方式获取 Class 对象(`SysUser.class` / `new SysUser().getClass()` / `Class.forName("course.SysUser")`),打印三个对象是否相等(`==` 结果应为 true) **思考题**(将答案写在代码文件头注释或提交报告里): 1. SysUser 有 2 个 private 构造方法,为什么 `getConstructor()` 拿不到它们?必须用什么方法组合?(提示:`getDeclaredConstructor` + `setAccessible(true)`,口诀"含 Declared 的才能拿私有") 2. public 构造和 private 构造,反射创建对象的方式有什么不同?多出来的 `setAccessible(true)` 做了什么? 3. 反射创建的对象是 `Object` 类型,怎么确认它确实是 SysUser?确认后如何调用 SysUser 的方法?(提示:`instanceof` + 强转) --- # 涵盖知识点总览 | 知识点 | 说明 | |--------|------| | `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) |