Просмотр исходного кода

feat: 新增20260812课后作业——反射遍历SysUser四个构造方法创建对象(由课堂练习一迁移为课后作业:public无参getConstructor+newInstance、public六参getConstructor(6个String.class)、private二参getDeclaredConstructor+setAccessible(true)暴力反射、private四参getDeclaredConstructor(4个String.class)+setAccessible(true)),含作业总体要求/命名要求/实现步骤/代码框架/输出示例/选做加分/思考题/涵盖知识点总览

WanJL 1 неделя назад
Родитель
Сommit
c919e20329
1 измененных файлов с 126 добавлено и 0 удалено
  1. 126 0
      课后作业/2026年8月12日-作业.md

+ 126 - 0
课后作业/2026年8月12日-作业.md

@@ -0,0 +1,126 @@
+# 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) |