Преглед изворни кода

docs: 更新20260813课堂笔记,同步代码变更——新增反射Method方法章节(Demo02:Class类获取Method对象的4个API getMethods/getMethod/getDeclaredMethods/getDeclaredMethod、重载方法必须传参数类型区分、Method类常用方法 invoke/setAccessible/getReturnType/getParameterTypes/getModifiers、invoke四种调用规律(实例方法传对象/静态方法传null/void返回null/private先setAccessible(true)暴力反射)、遍历方法输出方法名/参数/返回值、invoke调用getName/setName实例方法、暴力反射调用private read()、调用private static write()传null、动态代理/测试框架/注解解释器的基础),同步更新笔记标题/目录/知识点全景总结/随堂练习要点/拓展阅读,Student实体类新增7组getter/setter与私有方法read/write,练习四答案参考exericse/OrmFieldMapTest.java,同步更新README授课笔记表与授课代码表

WanJL пре 1 недеља
родитељ
комит
1c31c77fbd

+ 2 - 2
README.md

@@ -46,7 +46,7 @@
 | 2026-08-10 | [线程操作与线程安全](./课堂笔记/01-JavaSE基础-笔记/20260810-笔记.md) |
 | 2026-08-11 | [volatile、Lock 锁与线程池](./课堂笔记/01-JavaSE基础-笔记/20260811-笔记.md) |
 | 2026-08-12 | [类加载机制与反射](./课堂笔记/01-JavaSE基础-笔记/20260812-笔记.md) |
-| 2026-08-13 | [反射 Field 属性/字段/变量](./课堂笔记/01-JavaSE基础-笔记/20260813-笔记.md) |
+| 2026-08-13 | [反射 Field 与 Method 字段/方法反射](./课堂笔记/01-JavaSE基础-笔记/20260813-笔记.md) |
 
 ## 二、授课代码
 
@@ -78,7 +78,7 @@
 | 2026-08-10 | 线程操作方法(Thread.sleep 休眠、线程调度方式、CPU 时间片随机性、线程优先级)、守护线程(setDaemon、JVM 退出机制)、线程生命周期(6 种状态)、线程操作方法(join/interrupt/yield/isAlive、Object 类 wait/notify)、线程安全问题(数据竞争、卖票问题、计数器问题、线程安全三大特性)、synchronized 线程同步(监视器锁、三种写法)、多线程三种实现方式综合练习、课后作业回顾(Callable+FutureTask 带返回值求和) | `c260810` | [`course`](./授课代码/c260810/src/course/) / [`exericse`](./授课代码/c260810/src/exericse/) / [`homework0808`](./授课代码/c260810/src/homework0808/) |
 | 2026-08-11 | volatile 关键字(解决可见性和有序性、不保证原子性)、JVM 内存模型(工作内存 CPU 缓存 vs 主内存)、可见性问题演示(程序永不退出 VolatileDemo)、计数器问题升级(volatile 不保证原子性、synchronized 保证原子性)、Lock 锁(ReentrantLock 可重入锁:lock/unlock/tryLock/tryLock(timeout)/lockInterruptibly 四种用法、unlock 必须放 finally、公平锁/非公平锁、synchronized vs Lock 七维对比(锁读读写分离/底层实现 AQS/JDK21 版本更新)、10000 线程 count 验证)、死锁(4 个必要条件、死锁复现、避免方法固定锁顺序/tryLock 超时/ConcurrentHashMap)、线程池(ThreadPoolExecutor:7 参数、执行流程、8 任务演示、getActiveCount/getQueue/shutdown)、课后作业回顾(homework0810 Demo_03 卖票问题 synchronized 修复) | `c260811` | [`course`](./授课代码/c260811/src/course/) / [`homework0810`](./授课代码/c260811/src/homework0810/) |
 | 2026-08-12 | 类的加载机制(java 文件编译→字节码 class 文件→类加载器→内存→JVM 解释→二进制机器码→执行、类加载器作用(也可能是 jar 包)、类加载 6 种时机、懒加载原则、加载过程 3 大步 5 小步:加载→链接(验证/准备/解析)→初始化、静态代码块/代码块/构造方法执行顺序演示 Demo01)、类加载器(三种类加载器:BootstrapClassLoader/PlatformClassLoader/SystemClassLoader、双亲委派层级、ClassLoader.getSystemClassLoader/getParent 获取父加载器演示 Demo02)、双亲委派模型(Demo03:委派机制、为什么需要双亲委派三个原因、getResourceAsStream 加载资源配置文件 + Properties 解析 prop.properties 数据库配置)、反射机制(Demo04:反射概念、普通调用 vs 反射调用 5 维对比、为什么需要反射、反射工作机制、反射核心类)、获取 Class 对象的三种方式(Demo05:类名.class/对象.getClass/Class.forName 演示 + Student/Person/Animal 辅助类)、反射 Constructor 构造方法(Demo06:getConstructors/getDeclaredConstructors 获取构造方法 + setAccessible(true) 暴力反射 + newInstance 创建对象 + Student 新增 3 个构造方法) | `c260812` | [`course`](./授课代码/c260812/src/course/) / [`src/prop.properties`](./授课代码/c260812/src/prop.properties) |
-| 2026-08-13 | 反射 Field 属性/字段/变量(Demo01:Class 类获取 Field 对象的 4 个 API——getFields/getField/getDeclaredFields/getDeclaredField(Declared 口诀:含 Declared 拿私有本类全部、不含 Declared 只拿 public 含父类继承)、Field 类的常用方法——get/set 读写属性值/setAccessible(true) 暴力反射/getType 类型/getName 属性名/getModifiers 修饰符 + Modifier.toString 解析、演示① getDeclaredFields 遍历输出全部 7 个字段的修饰符/类型/属性名、演示② getField+get/set 读取修改 public 属性、演示③ getDeclaredField+setAccessible(true) 暴力反射读取修改 private 属性、演示④ 操作静态属性 get/set 对象参数传 null、反射赋值与普通访问同一份数据、ORM 框架用 Field.set() 把数据库数据映射到 Java 类的底层原理)+ Student 实体类(private 四字段 + public 两字段 + public static 字段 + 4 个构造方法) | `c260813` | [`course`](./授课代码/c260813/src/course/) |
+| 2026-08-13 | 反射 Field 属性/字段/变量(Demo01:Class 类获取 Field 对象的 4 个 API——getFields/getField/getDeclaredFields/getDeclaredField(Declared 口诀:含 Declared 拿私有本类全部、不含 Declared 只拿 public 含父类继承)、Field 类的常用方法——get/set 读写属性值/setAccessible(true) 暴力反射/getType 类型/getName 属性名/getModifiers 修饰符 + Modifier.toString 解析、演示① getDeclaredFields 遍历输出全部 7 个字段的修饰符/类型/属性名、演示② getField+get/set 读取修改 public 属性、演示③ getDeclaredField+setAccessible(true) 暴力反射读取修改 private 属性、演示④ 操作静态属性 get/set 对象参数传 null、反射赋值与普通访问同一份数据、ORM 框架用 Field.set() 把数据库数据映射到 Java 类的底层原理)+ 反射 Method 方法(Demo02:Class 类获取 Method 对象的 4 个 API——getMethods/getMethod/getDeclaredMethods/getDeclaredMethod(重载方法必须传参数类型区分)、Method 类的常用方法——invoke 调用方法/setAccessible(true) 暴力反射/getReturnType 返回值类型/getParameterTypes 参数类型数组/getModifiers 修饰符、invoke 四种调用规律(实例方法传对象/静态方法传 null/void 返回 null/private 先暴力反射)、遍历方法输出方法名/参数/返回值、invoke 调用 getName/setName 实例方法、暴力反射调用 private read()、调用 private static write() 传 null、动态代理/测试框架/注解解释器的基础)+ Student 实体类(private 四字段 + public 两字段 + public static 字段 + 4 个构造方法 + 7 组 getter/setter + 私有方法 read/write) | `c260813` | [`course`](./授课代码/c260813/src/course/) / [`exericse`](./授课代码/c260813/src/exericse/) |
 
 ## 三、课堂练习题
 

+ 96 - 0
授课代码/c260813/src/course/Demo02.java

@@ -0,0 +1,96 @@
+package course;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Demo02
+ * @description 反射 Method 方法
+ * @create 2026/8/13
+ */
+public class Demo02 {
+    /*
+        Method对象代表类中的一个方法,反射通过Method.invoke(对象,参数...)来调用方法,
+        就等价于 对象.方法(参数)
+        但是方法的名称和参数都是运行时才确定的,它就是动态代理、测试框架、注解解释器等等功能的基础。
+        Class对象获取Method对象的方法:
+        public Method[] getMethods()    返回所有的public方法,包括父类/接口继承的,比如toString
+        public Method getMethod(String name, Class<?>... parameterTypes)    返回指定的单个public方法
+        public Method[] getDeclaredMethods() 返回所有的方法,含有private,但不包括父类/接口的方法
+        public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回指定的单个方法含有private
+
+        如果遇到重载的方法(方法名相同,参数列表不同)那么就必须要指明参数的类型比如:
+        getMethod("setName", String.class)  中的String.class就是用来区分同名方法重载的,
+        如果参数类型不写,或写错,就会抛异常。
+
+         Method对象的方法:
+         public Object invoke(Object obj, Object... args)   调用方法,返回方法的执行结果
+            obj 是某个对象,指的是执行某个对象的指定方法
+            args 参数列表,调用方法时需要传入的实际参数
+         public void setAccessible(boolean flag)    暴力反射
+         public Class<?> getReturnType()    获取方法的返回值类型
+         public Class<?>[] getParameterTypes()  获取方法的参数类型数组
+         public int getModifiers() 获取方法的修饰符
+
+         注意:
+            如果是实例方法(通过对象调用的) invoke(对象,参数...) 第一个参数是调用该方法的对象
+            如果是类方法(使用static修饰的类方法)  invoke(null,参数...)  第一个参数是null
+            如果没有返回值(void):调用invoke()会返回null
+            如果是private方法,那么必须要先暴力反射setAccessible(true)
+     */
+    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<Student> studentClass = Student.class;
+
+        //1、获取所有的public方法
+        Method[] methods = studentClass.getMethods();
+        for (Method method : methods){
+            Class<?>[] parameterTypes = method.getParameterTypes();
+
+            List<String> parameters = Arrays.stream(parameterTypes).map(p -> p.getSimpleName()).collect(Collectors.toList());
+
+            System.out.println(method.getName()+"("+parameters+") 返回值="+method.getReturnType().getSimpleName());
+        }
+
+        System.out.println("========本类的所有方法==========");
+        for (Method method: studentClass.getDeclaredMethods()){
+
+            Class<?>[] parameterTypes = method.getParameterTypes();
+            List<String> parameters = Arrays.stream(parameterTypes).map(p -> p.getSimpleName()).collect(Collectors.toList());
+
+            System.out.println(method.getName()+"("+parameters+") 返回值="+method.getReturnType().getSimpleName());
+
+        }
+
+        //2、执行调用某个对象的实例方法
+        Student s=new Student(1001,"张三",25,"男","zhangsan@163.com","13636363366");
+        //通过Class对象获取Student的getName放啊
+        Method getNameMethod = studentClass.getMethod("getName");
+        //执行方法
+        Object name = getNameMethod.invoke(s);
+        System.out.println(name);
+
+        Method setNameMethod = studentClass.getMethod("setName", String.class);
+        setNameMethod.invoke(s, "李四");  //赋值操作不需要返回值
+        System.out.println(s.getName());
+
+
+        //暴力反射,执行私有方法
+        Method readMethod = studentClass.getDeclaredMethod("read");
+        //暴力反射
+        readMethod.setAccessible(true);
+        readMethod.invoke(s);   //执行方法
+
+        //执行静态方法
+        Method writeMethod = studentClass.getDeclaredMethod("write");
+        writeMethod.setAccessible(true);
+        writeMethod.invoke(null);
+    }
+
+
+
+}

+ 63 - 0
授课代码/c260813/src/course/Student.java

@@ -41,6 +41,69 @@ public class Student{
         this.phone = phone;
     }
 
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public String getGender() {
+        return gender;
+    }
+
+    public void setGender(String gender) {
+        this.gender = gender;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public static String getSchool() {
+        return school;
+    }
+
+    public static void setSchool(String school) {
+        Student.school = school;
+    }
+
+    private void read(){
+        System.out.println(this.name+"读.......");
+    }
+
+    private static void write(){
+        System.out.println("静态方法...写...............");
+    }
     public void study(){
         System.out.println(name+"在学习.....");
     }

+ 65 - 0
授课代码/c260813/src/exericse/OrmFieldMapTest.java

@@ -0,0 +1,65 @@
+package exericse;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title OrmFieldMapTest
+ * @description
+ * @create 2026/8/13
+ */
+
+public class OrmFieldMapTest {
+    public static void main(String[] args) throws Exception {
+        // ===== 第 1 部分:操作静态字段 school(对象参数传 null)=====
+        Class<Student> studentClass = Student.class;
+        // 1. 获取 school 字段 + 放开访问权限
+        Field schoolField = studentClass.getDeclaredField("school");
+        schoolField.setAccessible(true);
+        // 2. schoolField.get(null) 读取、schoolField.set(null, "哈尔滨佛学院") 修改
+        System.out.println(schoolField.get(null));
+        schoolField.set(null,"哈尔滨佛学院");
+        // 3. Student.school 直接访问验证
+        System.out.println(Student.school);
+
+        // ===== 第 2 部分:模拟 ORM —— 数据库行 → Java 对象 =====
+        // 4. 创建 Map 模拟数据库一行记录(key=字段名,value=值)
+        Map<String, Object> row = new HashMap<>();
+        // row.put("id", 1001); row.put("name", "张三"); ...
+        row.put("id", 1001);
+        row.put("name", "张三");
+        row.put("age",25);
+        // 5. 调用通用方法,把"数据库行"映射成 Student 对象
+        Object obj = mapToObject(row, Student.class);
+
+        // 6. 打印映射结果 + 强转调用 study() 验证
+        System.out.println(obj);
+        if (obj instanceof Student){
+            Student student=(Student) obj;
+            student.study();
+        }
+    }
+
+    // 通用映射方法:把 Map(数据库一行记录)映射成 clazz 的对象 —— ORM 底层原理
+    public static Object mapToObject(Map<String, Object> row, Class<?> clazz) throws Exception {
+
+        // 1. 反射创建空对象(getConstructor().newInstance())
+        Object obj = clazz.getConstructor().newInstance();
+        // 2. getDeclaredFields() 遍历该类全部字段
+        Field[] fields = clazz.getDeclaredFields();
+        for (Field f:fields){
+            // 3. 字段名在 row 里 → setAccessible(true) → field.set(obj, row.get(fieldName))
+            String fieldName = f.getName();
+            f.setAccessible(true);  //暴力反射
+            //根据filedName(Map集合的键)获取对应的value值,并且把这个值,赋值到obj对象中
+            f.set(obj,row.get(fieldName));
+        }
+        // 4. 返回映射好的对象
+        return obj;
+    }
+
+
+
+}

+ 40 - 0
授课代码/c260813/src/exericse/Student.java

@@ -0,0 +1,40 @@
+package exericse;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Student
+ * @description
+ * @create 2026/8/13
+ */
+public class Student {
+    private Integer id;
+    private String name;
+    private Integer age;
+    public static String school;
+
+    public Student() {
+    }
+
+    public Student(Integer id, String name, Integer age) {
+        this.id = id;
+        this.name = name;
+        this.age = age;
+    }
+
+    @Override
+    public String toString() {
+        return "Student{" +
+                "id=" + id +
+                ", name='" + name + '\'' +
+                ", age=" + age +
+                '}';
+    }
+    public void study(){
+        System.out.println(this.name+"在学习");
+    }
+    public static void main(String[] args) {
+        Student s1 = new Student(1001, "张三", 25);
+        Student s2 = new Student(1002, "李四", 30);
+    }
+}

+ 328 - 13
课堂笔记/01-JavaSE基础-笔记/20260813-笔记.md

@@ -1,10 +1,10 @@
-# 20260813 课堂笔记 — 反射 Field 属性/字段/变量
+# 20260813 课堂笔记 — 反射 Field 字段反射与 Method 方法反射
 
 - **日期**:2026-08-13
 - **项目**:`c260813`
 - **包路径**:`course`
 - **作者**:WanJL
-- **内容概览**:反射 Field(属性/字段/变量)(Demo01 演示:Class 类获取 Field 对象的 4 个 API → 获取所有属性并输出修饰符和类型 → 读取/修改 public 属性 → setAccessible(true) 暴力反射读取/修改 private 属性 → 操作静态属性传 null)+ Student 实体类(private/public/public static 字段设计 + 4 个构造方法)
+- **内容概览**:反射 Field(属性/字段/变量)(Demo01 演示:Class 类获取 Field 对象的 4 个 API → 获取所有属性并输出修饰符和类型 → 读取/修改 public 属性 → setAccessible(true) 暴力反射读取/修改 private 属性 → 操作静态属性传 null)+ 反射 Method(方法)(Demo02 演示:Class 类获取 Method 对象的 4 个 API → 遍历方法输出方法名/参数/返回值 → invoke 调用实例方法/带参方法/私有方法/静态方法)+ Student 实体类(private/public/public static 字段设计 + 4 个构造方法 + 7 组 getter/setter + 私有方法 read/write
 
 ---
 
@@ -18,9 +18,13 @@
 6. [Demo01 演示③:读取/修改 private 属性——暴力反射 setAccessible(true)](#6-demo01-演示③读取修改-private-属性暴力反射-setaccessibletrue)
 7. [Demo01 演示④:操作静态属性——对象参数传 null](#7-demo01-演示④操作静态属性对象参数传-null)
 8. [Student 实体类解析:三种字段权限的反射目标](#8-student-实体类解析三种字段权限的反射目标)
-9. [知识点全景总结](#9-知识点全景总结)
-10. [随堂练习要点](#10-随堂练习要点)
-11. [拓展阅读](#11-拓展阅读)
+9. [反射 Method 方法概述:方法的反射操作(Demo02)](#9-反射-method-方法概述方法的反射操作demo02)
+10. [获取 Method 对象的 4 个 API:Declared 与重载参数](#10-获取-method-对象的-4-个-apideclared-与重载参数)
+11. [Method 类的常用方法:invoke/setAccessible/getReturnType/getParameterTypes/getModifiers](#11-method-类的常用方法invokesetaccessiblegetreturntypegetparametertypesgetmodifiers)
+12. [Demo02 演示:遍历方法 + invoke 调用实例/带参/私有/静态方法](#12-demo02-演示遍历方法-invoke-调用实例带参私有静态方法)
+13. [知识点全景总结](#13-知识点全景总结)
+14. [随堂练习要点](#14-随堂练习要点)
+15. [拓展阅读](#15-拓展阅读)
 
 ---
 
@@ -398,6 +402,16 @@ public class Student{
         this.phone = phone;
     }
 
+    // …… 7 组 getter/setter(id/name/age/gender/email/phone/school)见下方补充……
+
+    private void read(){
+        System.out.println(this.name+"读.......");
+    }
+
+    private static void write(){
+        System.out.println("静态方法...写...............");
+    }
+
     public void study(){
         System.out.println(name+"在学习.....");
     }
@@ -425,6 +439,41 @@ public class Student{
 | `Student(Integer id, String name, Integer age, Integer gender)` | public | 四参 |
 | `Student(Integer id, String name, Integer age, Integer gender, String email, String phone)` | public | 六参(本课 Demo01 创建对象用) |
 
+### 代码更新:新增 7 组 getter/setter 与 2 个私有方法(Demo02 的反射目标)
+
+Student 类同步更新,新增了**每个字段对应的 getter/setter**(id/name/age/gender/email/phone/school 共 7 组,school 的 getter/setter 是 **static** 的),以及 **2 个私有方法** `read()` / `write()`——它们正是 Demo02 方法反射(Method)的调用目标:
+
+```java
+// 来源:course/Student.java(代码更新新增部分)
+public Integer getId() { return id; }
+public void setId(Integer id) { this.id = id; }
+public String getName() { return name; }
+public void setName(String name) { this.name = name; }
+// …… age/gender/email/phone 的 getter/setter 同理 ……
+public static String getSchool() { return school; }
+public static void setSchool(String school) { Student.school = school; }   // 静态 setter 用 类名.静态字段 赋值
+
+private void read(){                       // private 实例方法:输出 name+"读......."
+    System.out.println(this.name+"读.......");
+}
+
+private static void write(){               // private 静态方法:输出"静态方法...写..............."
+    System.out.println("静态方法...写...............");
+}
+```
+
+| 新增成员 | 类型 | 作用 / 对应演示 |
+|----------|------|----------------|
+| `getId/setId` ~ `getPhone/setPhone` 共 5 组 | public 实例 getter/setter | Demo02 用 `getMethod("getName")` / `getMethod("setName", String.class)` 反射调用 |
+| `getSchool/setSchool` | **public static** getter/setter | static 修饰的 getter/setter——调用静态方法 invoke 第一个参数传 null |
+| `read()` | **private 实例方法** | 暴力反射目标——`getDeclaredMethod("read")` + `setAccessible(true)` + `invoke(s)` |
+| `write()` | **private 静态方法** | 暴力反射 + 静态方法目标——`getDeclaredMethod("write")` + `setAccessible(true)` + `invoke(null)` |
+
+> **要点**:
+> - **getter/setter 是反射 Method 最典型的调用对象**:`getMethod("setName", String.class)` 反射调用 setName 等价于 `s.setName("李四")`——框架(MyBatis/Spring)反射调用 setter 给属性赋值、getter 取属性值正是本课的典型应用
+> - **private 方法必须暴力反射**:`read()` / `write()` 是 private,必须 `getDeclaredMethod` 拿到 + `setAccessible(true)` 放开权限才能 `invoke`
+> - **静态方法 invoke 传 null**:`write()` 是 static,`invoke(null)` 即可调用(与 Field 操作静态属性传 null 同一规律)
+
 > **要点**:
 > - **字段刻意混合 public / private / static**:就是为了让同一份反射代码展示三种操作路径——`getField`(public)、`getDeclaredField + setAccessible`(private)、`get/set(null)`(static)
 > - **本课用六参构造创建对象**:`new Student(1001, "张三", 25, "男", "zhangsan@163.com", "13636363366")`——因为 email、phone 是 public 字段,构造里可以给它们赋值
@@ -432,7 +481,235 @@ public class Student{
 
 ---
 
-## 9. 知识点全景总结
+## 9. 反射 Method 方法概述:方法的反射操作(Demo02)
+
+### 概念 —— Method 对象代表类中的一个方法
+
+**Method 对象代表类中的一个方法**。反射通过 `Method.invoke(对象, 参数...)` 来调用方法,**等价于 `对象.方法(参数)`**——但方法的名称和参数都是**运行时才确定**的。这是反射三大核心成员(Constructor / Field / Method)的最后一位,也是**动态代理、测试框架、注解解释器**等高级功能的基础。
+
+```java
+// 来源:course/Demo02.java(类注释)
+/*
+    Method对象代表类中的一个方法,反射通过Method.invoke(对象,参数...)来调用方法,
+    就等价于 对象.方法(参数)
+    但是方法的名称和参数都是运行时才确定的,它就是动态代理、测试框架、注解解释器等等功能的基础。
+*/
+```
+
+### 反射调用方法 vs 普通调用方法
+
+| 对比 | 普通方式 | 反射方式 |
+|------|----------|----------|
+| 调用方法 | `对象.方法名(参数)`(如 `s.study()`) | `method.invoke(对象, 参数...)` |
+| 方法的名称 | 编译期写死 | **运行时才确定**(可以是字符串变量/配置) |
+| 私有方法 | 编译期直接报错(private 不可见) | `getDeclaredMethod` + `setAccessible(true)` 可调用 |
+| 静态方法 | `类名.方法名()` | `invoke(null, 参数...)` |
+| 应用场景 | 普通业务 | 动态代理 / 测试框架(JUnit)/ 注解解释器 / 框架调用 setter |
+
+> **要点**:
+> - **invoke 等价于 `对象.方法(参数)`**——反射调用方法就是"运行时动态调用"
+> - **方法与 Field/Constructor 套路一致**:`getMethod(s)`(public 含继承)vs `getDeclaredMethod(s)`(本类全部含 private)+ `setAccessible(true)` 暴力反射
+> - **典型应用**:框架反射调用实体类的 setter 给属性赋值、getter 取属性值;测试框架反射调用被测试方法;动态代理底层基于 Method.invoke
+
+---
+
+## 10. 获取 Method 对象的 4 个 API:Declared 与重载参数
+
+### 概念 —— Class 类获取 Method 对象的四个方法
+
+```java
+// 来源:course/Demo02.java(类注释)
+/*
+    Class对象获取Method对象的方法:
+    public Method[] getMethods()    返回所有的public方法,包括父类/接口继承的,比如toString
+    public Method getMethod(String name, Class<?>... parameterTypes)    返回指定的单个public方法
+    public Method[] getDeclaredMethods() 返回所有的方法,含有private,但不包括父类/接口的方法
+    public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回指定的单个方法含有private
+*/
+```
+
+### 4 个 API 对比表
+
+| 方法 | 作用 | 是否含 private | 是否含父类/接口继承 |
+|------|------|----------------|---------------------|
+| `getMethods()` | 返回**所有 public 方法**数组 | ❌ 只 public | ✅ 含父类/接口继承的(如 `toString`/`hashCode`) |
+| `getMethod(name, parameterTypes)` | 返回**指定的单个 public 方法** | ❌ 只 public | ✅ 含父类/接口继承的 |
+| `getDeclaredMethods()` | 返回**本类所有方法**数组 | ✅ 含 private | ❌ 不含父类/接口的方法 |
+| `getDeclaredMethod(name, parameterTypes)` | 返回**指定的单个方法** | ✅ 含 private | ❌ 不含父类/接口的方法 |
+
+> **要点**:
+> - **口诀与 Field/Constructor 完全一致**:**含 `Declared` 的能拿到私有(本类全部、不含父类/接口);不含 `Declared` 的只能拿 public(含父类/接口继承)**
+> - **`getMethods()` 会包含继承的方法**:比如 Student 没写 `toString`,但 `getMethods()` 能拿到 Object 的 `toString`/`hashCode`/`equals`/`getClass` 等——这是 Method 与 Field 的"含继承"表现(Field 的 `getFields()` 也含父类 public 字段)
+
+### 重载方法必须指明参数类型
+
+```java
+// 来源:course/Demo02.java(类注释)
+/*
+    如果遇到重载的方法(方法名相同,参数列表不同)那么就必须要指明参数的类型比如:
+    getMethod("setName", String.class)  中的String.class就是用来区分同名方法重载的,
+    如果参数类型不写,或写错,就会抛异常。
+*/
+```
+
+| 写法 | 说明 |
+|------|------|
+| `getMethod("setName", String.class)` | 指定参数类型,找到 `setName(String)` 这个重载版本 |
+| `getMethod("setName")` | 不写参数类型——如果存在多个同名重载方法,**无法区分会抛异常**(NoSuchMethodException) |
+| `getMethod("getAge", Integer.class)` | 参数类型写错也会抛异常——必须与实际方法签名完全匹配 |
+
+> **要点**:
+> - **同名重载方法(方法名相同、参数列表不同)必须传参数类型来区分**——`String.class` 就是用来区分哪个重载版本的
+> - **参数类型不写或写错都会抛异常**(`NoSuchMethodException`)——所以 `getMethod("setName", String.class)` 中的 `String.class` 必不可少
+
+---
+
+## 11. Method 类的常用方法:invoke/setAccessible/getReturnType/getParameterTypes/getModifiers
+
+### 概念 —— 拿到 Method 对象后可以做什么
+
+```java
+// 来源:course/Demo02.java(类注释)
+/*
+     Method对象的方法:
+     public Object invoke(Object obj, Object... args)   调用方法,返回方法的执行结果
+        obj 是某个对象,指的是执行某个对象的指定方法
+        args 参数列表,调用方法时需要传入的实际参数
+     public void setAccessible(boolean flag)    暴力反射
+     public Class<?> getReturnType()    获取方法的返回值类型
+     public Class<?>[] getParameterTypes()  获取方法的参数类型数组
+     public int getModifiers() 获取方法的修饰符
+*/
+```
+
+| 方法 | 作用 | 说明 |
+|------|------|------|
+| `invoke(Object obj, Object... args)` | **调用方法**,返回方法的执行结果 | `obj` 是执行该方法的对象,`args` 是实际参数列表;返回 `Object`(可强转) |
+| `setAccessible(boolean flag)` | **暴力反射**:临时取消访问权限检查 | 调用 private 方法前必须 `setAccessible(true)` |
+| `getReturnType()` | **获取方法的返回值类型** | 返回 `Class<?>`(如 String.class / void.class) |
+| `getParameterTypes()` | **获取方法的参数类型数组** | 返回 `Class<?>[]`,逐个可取参数类型 |
+| `getModifiers()` | **获取方法的修饰符** | 返回 int,用 `Modifier.toString()` 解析 |
+
+### invoke 的四种调用规律(重点)
+
+```java
+// 来源:course/Demo02.java(类注释)
+/*
+     注意:
+        如果是实例方法(通过对象调用的) invoke(对象,参数...) 第一个参数是调用该方法的对象
+        如果是类方法(使用static修饰的类方法)  invoke(null,参数...)  第一个参数是null
+        如果没有返回值(void):调用invoke()会返回null
+        如果是private方法,那么必须要先暴力反射setAccessible(true)
+*/
+```
+
+| 方法类型 | invoke 写法 | 说明 |
+|----------|-------------|------|
+| **public 实例方法** | `invoke(对象, 参数...)` | 第一个参数是**调用该方法的对象**(如 `invoke(s)` 等价于 `s.getName()`) |
+| **static 静态方法** | `invoke(null, 参数...)` | 第一个参数是 **null**(类方法不属于对象,与 Field 操作静态属性传 null 同一规律) |
+| **void 无返回值方法** | `invoke(对象, 参数...)` | 调用 `invoke()` 会返回 **null**(void 方法没有返回值) |
+| **private 私有方法** | 先 `setAccessible(true)` 再 `invoke(...)` | 必须暴力反射放开权限,否则抛 IllegalAccessException |
+
+> **要点**:
+> - **invoke 第一参数 = 调用方法的对象**:实例方法传对象、**静态方法传 null**(回顾 Field 操作静态属性传 null 的同一规律)
+> - **invoke 返回 Object**:方法有返回值时 `invoke` 返回该返回值(可强转成目标类型);**void 方法返回 null**
+> - **private 方法必须暴力反射**:`getDeclaredMethod` 拿到 + `setAccessible(true)` + `invoke`——与 Field/Constructor 的暴力反射套路完全一致
+> - **反射三大成员统一套路**:`getDeclaredXxx` 拿私有 + `setAccessible(true)` 放开权限 + 执行操作(Constructor→newInstance / Field→get/set / Method→invoke)
+
+---
+
+## 12. Demo02 演示:遍历方法 + invoke 调用实例/带参/私有/静态方法
+
+### 概念 —— 完整走一遍"拿 Class → 遍历方法 → 调用方法"
+
+Demo02 演示了方法反射的**全部四个应用**:遍历所有方法(含参数和返回值信息)、调用 public 实例方法(无参/带参)、暴力反射调用 private 实例方法、调用 static 静态方法。
+
+```java
+// 来源:course/Demo02.java
+public class Demo02 {
+    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<Student> studentClass = Student.class;
+
+        //1、获取所有的public方法(含父类/接口继承的,如toString)
+        Method[] methods = studentClass.getMethods();
+        for (Method method : methods){
+            Class<?>[] parameterTypes = method.getParameterTypes();
+            List<String> parameters = Arrays.stream(parameterTypes)
+                    .map(p -> p.getSimpleName()).collect(Collectors.toList());
+            System.out.println(method.getName()+"("+parameters+") 返回值="+method.getReturnType().getSimpleName());
+        }
+
+        System.out.println("========本类的所有方法==========");
+        // getDeclaredMethods() 遍历本类全部方法(含 private)
+        for (Method method: studentClass.getDeclaredMethods()){
+            Class<?>[] parameterTypes = method.getParameterTypes();
+            List<String> parameters = Arrays.stream(parameterTypes)
+                    .map(p -> p.getSimpleName()).collect(Collectors.toList());
+            System.out.println(method.getName()+"("+parameters+") 返回值="+method.getReturnType().getSimpleName());
+        }
+
+        //2、执行调用某个对象的实例方法
+        Student s=new Student(1001,"张三",25,"男","zhangsan@163.com","13636363366");
+        // 调用 public 无参实例方法 getName()——invoke 返回 Object
+        Method getNameMethod = studentClass.getMethod("getName");
+        Object name = getNameMethod.invoke(s);
+        System.out.println(name);
+
+        // 调用 public 带参实例方法 setName(String)——重载必须指明参数类型
+        Method setNameMethod = studentClass.getMethod("setName", String.class);
+        setNameMethod.invoke(s, "李四");   //赋值操作不需要返回值
+        System.out.println(s.getName());
+
+        //暴力反射,执行私有方法 read()——private 实例方法
+        Method readMethod = studentClass.getDeclaredMethod("read");
+        readMethod.setAccessible(true);
+        readMethod.invoke(s);   //执行方法
+
+        //执行静态方法 write()——static 方法 invoke 传 null
+        Method writeMethod = studentClass.getDeclaredMethod("write");
+        writeMethod.setAccessible(true);
+        writeMethod.invoke(null);
+    }
+}
+```
+
+### 预期输出与运行要点
+
+```
+...(getMethods() 输出所有 public 方法:getId/setId/getName/setName/.../study + Object 继承的 toString/hashCode/equals/getClass 等)...
+========本类的所有方法==========
+setName([String]) 返回值=void
+setSchool([String]) 返回值=void
+write() 返回值=void
+getSchool() 返回值=String
+...
+张三                    ← getMethod("getName").invoke(s) 返回 name 值
+李四                    ← getMethod("setName", String.class).invoke(s, "李四") 后 s.getName()
+李四读.......           ← 暴力反射调用 private read():name 已是"李四"
+静态方法...写...............   ← 暴力反射调用 private static write():invoke(null)
+```
+
+| 代码 | 作用 | 说明 |
+|------|------|------|
+| `studentClass.getMethods()` | 获取**所有 public 方法**(含父类/接口继承) | 遍历打印方法名、参数类型、返回值类型 |
+| `method.getParameterTypes()` | 获取**参数类型数组** | `Arrays.stream(...)` 用 Stream 流把 `Class<?>` 映射成简单名 List(回顾 Stream 流知识) |
+| `method.getReturnType().getSimpleName()` | 获取**返回值类型**简单名 | 如 String / void |
+| `studentClass.getDeclaredMethods()` | 获取**本类全部方法**(含 private,不含父类/接口) | 输出比 getMethods 多出 read/write 两个私有方法 |
+| `studentClass.getMethod("getName")` | 获取 public 无参方法 | `invoke(s)` 等价于 `s.getName()`,返回 Object 打印 `张三` |
+| `studentClass.getMethod("setName", String.class)` | 获取 **public 带参方法**(指明参数类型区分重载) | `invoke(s, "李四")` 等价于 `s.setName("李四")`,赋值操作不需要返回值 |
+| `getDeclaredMethod("read")` + `setAccessible(true)` + `invoke(s)` | **暴力反射调用 private 实例方法** | 必须放开权限;name 已改为"李四",输出 `李四读.......` |
+| `getDeclaredMethod("write")` + `setAccessible(true)` + `invoke(null)` | **暴力反射调用 private 静态方法** | 静态方法 invoke 第一参数传 **null**,输出 `静态方法...写...............` |
+
+> **要点**:
+> - **getMethods() 含继承方法**:Student 没写 `toString`,但 getMethods() 能拿到 Object 的 `toString`/`hashCode` 等——Demo02 用 Stream 流把参数类型 `Class<?>[]` 转成 `List<String>` 简单名再打印
+> - **getMethod 调用实例方法**:`invoke(s)` 第一个参数是执行方法的对象;带参方法 `invoke(s, "李四")` 传实际参数
+> - **void 方法返回值**:`setName` 是 void,`invoke` 返回 null,不需要接收返回值
+> - **私有方法必须暴力反射**:`read()`/`write()` 是 private,用 `getDeclaredMethod` + `setAccessible(true)`;**静态方法 invoke 传 null**
+> - **与 Field 反射呼应**:操作静态成员(属性/方法)对象参数都传 null——本课 Field 操作静态属性 + Method 调用静态方法,规律统一
+
+---
+
+## 13. 知识点全景总结
 
 | 知识点 | 核心内容 | 来源 |
 |--------|----------|------|
@@ -458,12 +735,29 @@ public class Student{
 | **反射赋值与普通访问同一份数据** | `field.set(s, ...)` 修改后 `s.email` / `Student.school` 直接访问也是新值 | course/Demo01 main |
 | **Student 字段设计** | private(id/name/age/gender)+ public(email/phone)+ public static(school)——三种权限对应三段演示 | course/Student.java |
 | **Student 构造方法** | public 无参 / private 二参 / public 四参 / public 六参——本课用六参构造创建对象,上一课演示过 Constructor 反射 | course/Student.java |
+| **Student 新增 getter/setter** | 7 组 getter/setter(id/name/age/gender/email/phone 实例 + school 静态)——Demo02 用 `getMethod("getName")`/`getMethod("setName", String.class)` 反射调用 | course/Student.java |
+| **Student 私有方法 read/write** | `private void read()`(实例)+ `private static void write()`(静态)——Demo02 暴力反射调用目标(`getDeclaredMethod` + `setAccessible(true)` + `invoke`) | course/Student.java |
 | **student.study()** | Student 的实例方法 `输出 name+"在学习....."` | course/Student.java |
-| **受检异常** | main 方法签名 throws `ClassNotFoundException, NoSuchFieldException, IllegalAccessException`——getField 字段名不存在抛 NoSuchFieldException、private 未放开权限 get/set 抛 IllegalAccessException、forName 类名错误抛 ClassNotFoundException | course/Demo01 main |
+| **Method 概念** | Method 对象代表类中的一个方法;反射通过 `Method.invoke(对象, 参数...)` 调用方法,**等价于 `对象.方法(参数)`**,方法名称和参数运行时才确定——动态代理/测试框架/注解解释器的基础 | course/Demo02 注释 |
+| **getMethods()** | 返回**所有 public 方法**数组,**包括父类/接口继承的**(如 toString/hashCode/getClass) | course/Demo02 注释 |
+| **getMethod(name, parameterTypes)** | 返回**指定的单个 public 方法**;重载方法必须传参数类型区分(如 `getMethod("setName", String.class)`),不写/写错抛异常 | course/Demo02 注释 |
+| **getDeclaredMethods()** | 返回**本类所有方法**数组,**包括 private,但不包括父类/接口的方法** | course/Demo02 注释 |
+| **getDeclaredMethod(name, parameterTypes)** | 返回**指定的单个方法**,**包括 private** | course/Demo02 注释 |
+| **Method.invoke(obj, args)** | **调用方法**,返回方法的执行结果(Object 可强转);`obj` 是执行该方法的对象,`args` 是实际参数 | course/Demo02 注释 |
+| **Method.setAccessible(true)** | **暴力反射**:临时取消访问权限检查,调用 private 方法必须调用 | course/Demo02 注释 |
+| **Method.getReturnType()** | 获取方法的**返回值类型**(如 String.class / void.class) | course/Demo02 注释 |
+| **Method.getParameterTypes()** | 获取方法的**参数类型数组**(`Class<?>[]`) | course/Demo02 注释 |
+| **Method.getModifiers()** | 获取方法的修饰符(返回 int,`Modifier.toString()` 解析) | course/Demo02 注释 |
+| **invoke 四种调用规律** | 实例方法 `invoke(对象,参数...)` 第一参数传对象;**静态方法 `invoke(null,参数...)` 传 null**;**void 方法 invoke 返回 null**;**private 方法必须先 setAccessible(true)** | course/Demo02 注释 |
+| **演示:遍历方法** | `getMethods()`/`getDeclaredMethods()` 遍历 + `getParameterTypes()`(Stream 映射成简单名 List)+ `getReturnType().getSimpleName()` 输出每个方法的方法名/参数/返回值 | course/Demo02 main |
+| **演示:调用实例方法** | `getMethod("getName")` + `invoke(s)` 调用无参方法返回 name;`getMethod("setName", String.class)` + `invoke(s, "李四")` 调用带参方法(void 不接收返回值) | course/Demo02 main |
+| **演示:暴力反射私有方法** | `getDeclaredMethod("read")` + `setAccessible(true)` + `invoke(s)` 调用 private 实例方法;`getDeclaredMethod("write")` + `setAccessible(true)` + `invoke(null)` 调用 private 静态方法(传 null) | course/Demo02 main |
+| **反射三大成员统一套路** | Constructor(newInstance 创建对象)/ Field(get/set 读写字段)/ Method(invoke 调用方法)——**Declared 拿私有 + setAccessible(true) 放开权限**,操作静态成员(属性/方法)传 null | course/Demo01 + Demo02 |
+| **受检异常** | Demo01 main throws `ClassNotFoundException, NoSuchFieldException, IllegalAccessException`(Field);Demo02 main throws `NoSuchMethodException, InvocationTargetException, IllegalAccessException`(Method)——方法名/参数类型不匹配抛 NoSuchMethodException、被调方法内部抛异常时 invoke 抛 InvocationTargetException | course/Demo01 + Demo02 main |
 
 ---
 
-## 10. 随堂练习要点
+## 14. 随堂练习要点
 
 - **Field 概念复述(必做)**:用一句话说清"什么是 Field 反射"——Field 对象代表类中的一个成员变量,反射通过 `get()` 读取字段值、`set()` 修改字段值;能说出框架中的应用(ORM 框架查询数据库后用 Field.set() 把数据映射到 Java 类)
 - **获取 Field 的 4 个 API 背诵(必做)**:`getFields()`(所有 public 数组,含父类继承)/ `getField(String name)`(指定 public)/ `getDeclaredFields()`(本类全部含 private,不含父类)/ `getDeclaredField(String name)`(指定含 private)——背口诀:**含 Declared 的能拿私有(本类全部),不含 Declared 的只能拿 public(含父类继承)**
@@ -475,17 +769,38 @@ public class Student{
 - **getField 拿私有字段实验**:把 Demo01 中 `clazz.getDeclaredField("name")` 改成 `clazz.getField("name")`,运行观察抛 **NoSuchFieldException**——体会"getField 只能拿 public 字段"的口诀
 - **静态属性传 null 理解(必做)**:思考为什么静态属性 get/set 的对象参数要传 null——静态成员(静态属性/静态方法/静态代码块)不属于某个对象,而是属于整个类;对比实例属性必须传对象(不同对象字段值不同)
 - **静态属性反射修改验证**:观察 `schoolField.set(null, "福建桥梁职业技术学院")` 之后 `Student.school` 直接访问输出新值——体会"反射 set 与普通访问同一份数据、静态字段全类共享"
-- **与 Constructor 反射对比(必做)**:回顾上一课(08-12 反射 Constructor)——获取 API 都是"含 Declared 拿私有、不含 Declared 只拿 public",访问私有成员都要 `setAccessible(true)`;对比 Constructor(newInstance 创建对象)与 Field(get/set 读写属性)的差异
-- **反射三大成员串联**:到目前为止已学 **Constructor**(创建对象)和 **Field**(读写字段属性),下一个核心成员是 **Method**(调用方法,`getMethod` + `invoke`)——套路与两者完全一致,提前预习
+- **与 Constructor 反射对比(必做)**:回顾上一课(08-12 反射 Constructor)——获取 API 都是"含 Declared 拿私有、不含 Declared 只拿 public",访问私有成员都要 `setAccessible(true)`;对比 Constructor(newInstance 创建对象)与 Field(get/set 读写字段)的差异
+- **反射三大成员串联(本课完结)**:反射三大核心成员已全部学完——**Constructor**(构造方法,08-12 创建对象)/ **Field**(字段属性,本课读写字段)/ **Method**(方法,本课调用方法)——三者套路完全一致:`getDeclaredXxx` 拿私有 + `setAccessible(true)` 放开权限 + 执行操作
 - **getDeclaredFields 遍历练习**:写一个通用工具方法 `printFields(Object obj)`:传入任意对象,用 `getDeclaredFields()` 遍历打印所有字段的修饰符/类型/属性名——体会"反射可以做通用工具"(回顾上一课 printUtil 思路)
 - **受检异常处理回顾**:观察 Demo01 main 方法签名 `throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException`——getField/getDeclaredField 字段名写错抛 NoSuchFieldException、private 未放开权限操作抛 IllegalAccessException、Class.forName 类名写错抛 ClassNotFoundException——回顾 07-28 异常处理知识
+- **Method 概念复述(必做)**:用一句话说清"什么是 Method 反射"——Method 对象代表类中的一个方法,反射通过 `Method.invoke(对象, 参数...)` 调用方法,等价于 `对象.方法(参数)`,方法的名称和参数运行时才确定;能说出应用场景(动态代理、测试框架、注解解释器、框架调用 setter/getter)
+- **获取 Method 的 4 个 API 背诵(必做)**:`getMethods()`(所有 public 数组,含父类/接口继承如 toString)/ `getMethod(name, parameterTypes)`(指定 public)/ `getDeclaredMethods()`(本类全部含 private,不含父类/接口)/ `getDeclaredMethod(name, parameterTypes)`(指定含 private)——口诀与 Field/Constructor 完全一致:**含 Declared 的能拿私有,不含 Declared 的只能拿 public**
+- **重载方法区分(必做)**:理解 `getMethod("setName", String.class)` 中的 `String.class` 是**用来区分同名重载方法**的——不写参数类型或写错都会抛 NoSuchMethodException;试着重载一个 `setName(String, Integer)` 并分别用两种签名获取
+- **Method 常用方法背诵**:`invoke(obj, 参数...)` 调用方法 / `setAccessible(true)` 暴力反射 / `getReturnType()` 返回值类型 / `getParameterTypes()` 参数类型数组 / `getModifiers()` 修饰符
+- **invoke 四种调用规律背诵(必做)**:①实例方法 `invoke(对象, 参数...)` 第一参数传对象 ②**静态方法 `invoke(null, 参数...)` 传 null** ③**void 方法 invoke 返回 null** ④**private 方法必须先 setAccessible(true)**——与 Field 操作静态属性传 null 同一规律
+- **Demo02 运行验证(必做)**:运行 `course/Demo02`,观察输出——`getMethods()` 遍历打印所有 public 方法(含 Object 继承的 toString/hashCode/getClass 等)+ Stream 处理参数类型、`getDeclaredMethods()` 输出本类全部方法(含 read/write 私有方法)、`getMethod("getName").invoke(s)` 打印"张三"、`getMethod("setName", String.class).invoke(s, "李四")` 后打印"李四"、暴力反射 `read()` 输出"李四读......."、静态方法 `write()` 输出"静态方法...写..............."
+- **invoke 调用实例 vs 静态对比实验**:分别用 `getMethod("getName")`(实例)和 `getMethod("getSchool")`(静态)调用——体会实例方法 invoke 第一参数传对象 s、静态方法传 null;把静态方法的 invoke 第一参数误传成对象 s,观察它是否也能执行(static 方法本质不依赖对象,传对象也会被忽略)
+- **暴力反射私有方法实验(必做)**:把 Demo02 中 `readMethod.setAccessible(true)` 注释掉再运行,观察抛 **IllegalAccessException**——体会"private 方法不放开权限无法 invoke"
+- **getMethod 拿私有方法实验**:用 `studentClass.getMethod("read")`(不带 Declared)尝试获取 private 方法,观察抛 **NoSuchMethodException**——验证"getMethod 只能拿 public"的口诀
+- **void 方法返回值验证**:`setNameMethod.invoke(s, "李四")` 返回 null(void 方法),打印 `System.out.println(setNameMethod.invoke(s, "李四"))` 观察输出 null;对比 `getNameMethod.invoke(s)` 返回 "张三"——体会"无返回值方法 invoke 返回 null"
+- **getMethods vs getDeclaredMethods 对比**:思考两者的区别——getMethods 拿 public + 父类/接口继承;getDeclaredMethods 拿本类全部(含 private)不含父类。数一数 Student 的 getMethods() 输出里有哪些是 Object 继承来的(toString/hashCode/equals/getClass/notify/wait 等)
+- **InvocationTargetException 理解**:把 `read()` 方法体内故意写一个会抛异常的语句(如 `int x = 1/0`),反射 `invoke` 调用它,观察抛 **InvocationTargetException**(被调方法内部异常被包装)——回顾 07-28 异常处理知识
+- **练习答案参考**:课堂练习四(模拟 ORM mapToObject)的参考答案代码在 `exericse/OrmFieldMapTest.java`(含 `exericse/Student.java` 实体类)——运行观察静态字段传 null 操作 + Map 数据库行映射到 Student 对象的完整流程
 
 ---
 
-## 11. 拓展阅读
+## 15. 拓展阅读
 
 - **反射 Field 在 ORM 框架中的落地**:MyBatis、Hibernate 等 ORM 框架的**结果映射(Result Mapping)**就是本课"Field.set() 把数据库数据映射到 Java 类"的经典实现——数据库表字段名对应 Java 实体属性名,查询结果通过反射 Field.set() 逐字段赋值
-- **反射三大核心成员进度**:本课完成了反射三大核心成员中的 **Constructor(构造方法,08-12)+ Field(字段属性,本课)**,还剩 **Method(方法)**——下一课将学习 `getMethods()` / `getDeclaredMethods()` / `getMethod(name, 参数类型)` + `method.invoke(对象, 参数)` 调用方法,套路与本课完全一致(Declared 拿私有 + setAccessible(true) 放开权限)
+- **反射三大核心成员(已全部学完)**:反射三大核心成员已全部掌握——**Constructor(构造方法,08-12 newInstance 创建对象)+ Field(字段属性,本课 get/set 读写字段)+ Method(方法,本课 invoke 调用方法)**——三者套路完全一致:`getDeclaredXxx` 拿私有 + `setAccessible(true)` 放开权限 + 执行操作;至此反射三件套(建对象/读写属性/调方法)可组合完成框架级操作
+- **Method 反射在动态代理中的落地**:**JDK 动态代理(Proxy + InvocationHandler)**底层就是 Method.invoke——代理对象调用任何方法都会被转发到 `InvocationHandler.invoke(proxy, method, args)`,其中 `method.invoke(target, args)` 反射调用真实对象的方法——这正是本课"Method 是动态代理的基础"论断的经典实现;后续学习 Spring AOP(基于动态代理)时会反复见到
+- **Method 反射在测试框架中的落地**:JUnit / TestNG 等**测试框架**通过反射 `getDeclaredMethods()` 遍历类的全部方法,找出带 `@Test` 注解的方法,再 `method.invoke(测试对象)` 执行——"注解 + 反射"是测试框架的底层原理,本课 Demo02 的遍历方法正是这个套路
+- **Method 反射在框架 setter/getter 调用中的落地**:Spring 的 BeanUtils / MyBatis 的结果映射都大量使用 `getMethod("set" + 属性名首字母大写, 类型.class)` + `invoke(obj, 值)` 反射调用 setter 赋值——这就是为什么实体类要写标准 getter/setter(本课 Student 新增的 7 组 getter/setter 正是为此准备)
+- **getParameterTypes 与重载的关联**:反射通过 `getParameterTypes()` 拿到方法的**参数类型数组**(`Class<?>[]`),这与 `getMethod(name, parameterTypes...)` 的传参一一对应——重载方法(同名不同参)在 Class 对象里其实是**多个独立的 Method 对象**,必须靠参数类型定位到具体那一个
+- **invoke 的参数匹配与自动装箱**:`invoke(obj, 参数...)` 传入的实际参数会与方法的参数类型匹配(基本类型自动装箱,如 setAge(Integer) 传 int 值 25 会被自动装箱成 Integer);参数类型不匹配或数量不对抛 `IllegalArgumentException`
+- **InvocationTargetException 的包装含义**:`invoke` 调用方法时,**如果被调方法内部抛异常,invoke 会把异常包装成 `InvocationTargetException` 抛出**(而不是直接抛原异常)——调用者需要 `getCause()` 拿到真正的异常;这是反射调用方法与普通调用的一个隐蔽差异
+- **Method.invoke 的 Class.newInstance 对比**:JDK9+ 推荐用 `Constructor.newInstance()`(可传参、可访问 private 构造),废弃了 `Class.newInstance()`(只能无参且权限检查严格)——同理反射调用方法统一用 `Method.invoke` 而非老旧的 `Class.getMethod` 直接裸调
+- **反射三件套组合的框架能力**:把本课的知识点组合起来——`getConstructor().newInstance()` 创建对象(08-12)+ `getDeclaredField().set()` 给字段赋值(Field)+ `getDeclaredMethod().invoke()` 调用方法(Method)——就是 MyBatis 结果映射、Spring Bean 初始化、测试框架执行测试用例的完整底层链路
 - **getModifiers() 的 int 常量**:Java 反射中修饰符以 **int 位掩码(bitmask)** 表示——public=1、private=2、protected=4、static=8、final=16...`Modifier.toString()` 内部就是按位与运算拼接出字符串;`Modifier.isPublic(int)` / `Modifier.isStatic(int)` 等 isXxx 方法可单独判断某个修饰符是否存在
 - **Field.setAccessible 与 JPMS**:`setAccessible(true)` 本质是**绕过 Java 访问控制检查**;在模块化系统(JPMS)中,跨模块访问私有成员还受 `--add-opens` 参数约束——Spring 等框架在 JDK17+ 运行时需要配置 JVM 参数放开模块限制
 - **反射的缓存优化**:反射 `getField`/`getDeclaredField` 本身有开销,框架(如 MyBatis)通常**在启动阶段一次性获取并缓存 Field 对象**,运行时只调用 `get()/set()`——这是"框架用反射但性能不差"的关键优化手段
@@ -494,5 +809,5 @@ public class Student{
 - **IDEA 调试器的实现原理**:IDEA 等 IDE 的**调试器变量查看窗口**能在运行时显示对象的所有字段值(包括 private)——底层就是反射 `getDeclaredFields()` + `setAccessible(true)` + `field.get(对象)`,与本课 Demo01 的演示逻辑一致
 - **JSON 序列化框架**:Jackson / Gson / Fastjson 把 Java 对象转成 JSON 字符串、或把 JSON 转回对象,底层也大量使用 Field 反射——读取对象所有字段名与值(序列化)、按 JSON 键名给对象字段赋值(反序列化)
 - **反射破坏封装性的辩证关系**:本课 Field 反射可以访问 private 字段、修改 final 字段,既是框架能力的来源,也是"破坏封装性"的体现——日常业务代码中应遵守上一课的原则:**正常业务用普通方式访问属性,反射留给框架与中间件**
-- **JDK 文档**:[`java.lang.Class`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html)(getFields/getField/getDeclaredFields/getDeclaredField)、[`java.lang.reflect.Field`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/Field.html)(get/set/setAccessible/getType/getName/getModifiers)、[`java.lang.reflect.Modifier`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/Modifier.html)(toString/isPublic/isStatic 等修饰符解析工具类)
+- **JDK 文档**:[`java.lang.Class`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html)(getFields/getField/getDeclaredFields/getDeclaredField + getMethods/getMethod/getDeclaredMethods/getDeclaredMethod)、[`java.lang.reflect.Field`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/Field.html)(get/set/setAccessible/getType/getName/getModifiers)、[`java.lang.reflect.Method`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/Method.html)(invoke/setAccessible/getReturnType/getParameterTypes/getModifiers)、[`java.lang.reflect.Modifier`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/Modifier.html)(toString/isPublic/isStatic 等修饰符解析工具类)