Kaynağa Gözat

fix: 修正20260812反射练习的代码框架——移除直接给出的答案代码,改为纯TODO填空式框架(练习一/二/三/四均只保留TODO提示描述+API方法名提示,如Class.forName/getConstructor/getDeclaredConstructor/setAccessible/invoke等,学生需自己动手补全代码),保留输出示例/实现步骤指导

WanJL 1 hafta önce
ebeveyn
işleme
43cf17ff1e
1 değiştirilmiş dosya ile 44 ekleme ve 84 silme
  1. 44 84
      课堂练习题/20260812-反射练习.md

+ 44 - 84
课堂练习题/20260812-反射练习.md

@@ -46,39 +46,27 @@ import java.lang.reflect.Constructor;
 
 
 public class ReflectCreateSysUserTest {
 public class ReflectCreateSysUserTest {
     public static void main(String[] args) throws Exception {
     public static void main(String[] args) throws Exception {
-        // ① Class.forName("全类名") 获取 SysUser 的 Class 对象
-        // TODO 1: Class<?> clazz = Class.forName("???");
-        Class<?> clazz = Class.forName("course.SysUser");
+        // ① 方式三:Class.forName("全类名") 获取 SysUser 的 Class 对象
+        // TODO 1: Class<?> clazz = Class.forName("???");   // ??? 填 SysUser 的全类名
 
 
-        // ② 统计构造方法:getConstructors 只能拿到 public(2 个),getDeclaredConstructors 能拿到全部(4 个,含 private)
-        System.out.println("public 构造方法个数:" + clazz.getConstructors().length);
-        System.out.println("全部构造方法个数(含private):" + clazz.getDeclaredConstructors().length);
+        // ② 统计构造方法:getConstructors() 只能拿到 public,getDeclaredConstructors() 能拿到全部(含 private)
+        // TODO 2: 打印两个方法返回数组的 length(应分别得到 2 和 4)
 
 
         // ③ 反射创建对象①:public 无参构造
         // ③ 反射创建对象①:public 无参构造
-        // TODO 2: Constructor<?> c1 = clazz.getConstructor();
-        Constructor<?> c1 = clazz.getConstructor();
-        Object obj1 = c1.newInstance();
-        System.out.println("① 无参构造:" + obj1 + "(是SysUser吗?" + (obj1 instanceof SysUser) + ")");
+        // TODO 3: 用 getConstructor() 获取无参构造 + newInstance() 创建对象,
+        //         打印对象并用 instanceof SysUser 判断,格式参考"输出示例①"
 
 
         // ④ 反射创建对象②:public 六参构造(id, username, password, name, phone, email)
         // ④ 反射创建对象②:public 六参构造(id, username, password, name, phone, email)
-        // TODO 3: getConstructor 传 6 个 String.class 参数类型
-        Constructor<?> c2 = clazz.getConstructor(String.class, String.class, String.class, String.class, String.class, String.class);
-        Object obj2 = c2.newInstance("1", "zhangsan", "123456", "张三", "13800000000", "zhangsan@qq.com");
-        System.out.println("② 六参构造:" + obj2);
-
-        // ⑤ 反射创建对象③:private 二参构造(username, password)—— 必须 setAccessible(true) 暴力反射!
-        // TODO 4: getDeclaredConstructor(String.class, String.class) + setAccessible(true)
-        Constructor<?> c3 = clazz.getDeclaredConstructor(String.class, String.class);
-        c3.setAccessible(true);
-        Object obj3 = c3.newInstance("admin", "admin888");
-        System.out.println("③ 私有二参构造:" + obj3);
-
-        // ⑥ 反射创建对象④:private 四参构造(id, name, phone, email)—— 同样需要暴力反射
-        // TODO 5: getDeclaredConstructor(4 个 String.class) + setAccessible(true)
-        Constructor<?> c4 = clazz.getDeclaredConstructor(String.class, String.class, String.class, String.class);
-        c4.setAccessible(true);
-        Object obj4 = c4.newInstance("2", "李四", "13900000000", "lisi@qq.com");
-        System.out.println("④ 私有四参构造:" + obj4);
+        // TODO 4: 用 getConstructor(6 个 String.class) 获取构造
+        //         + newInstance("1","zhangsan","123456","张三","13800000000","zhangsan@qq.com") 创建并打印
+
+        // ⑤ 反射创建对象③:private 二参构造(username, password)—— 必须暴力反射!
+        // TODO 5: 用 getDeclaredConstructor(String.class, String.class) 获取 private 构造
+        //         + setAccessible(true) 放开权限 + newInstance("admin","admin888") 创建并打印
+
+        // ⑥ 反射创建对象④:private 四参构造(id, name, phone, email)
+        // TODO 6: 用 getDeclaredConstructor(4 个 String.class) 获取 private 构造
+        //         + setAccessible(true) + newInstance("2","李四","13900000000","lisi@qq.com") 创建并打印
     }
     }
 }
 }
 ```
 ```
@@ -136,40 +124,26 @@ import java.lang.reflect.Field;
 public class ReflectSetFieldTest {
 public class ReflectSetFieldTest {
     public static void main(String[] args) throws Exception {
     public static void main(String[] args) throws Exception {
         // ① 获取 Class 对象 + 反射创建对象(复用练习一的四步链)
         // ① 获取 Class 对象 + 反射创建对象(复用练习一的四步链)
-        Class<?> clazz = Class.forName("course.Student");
-        Object obj = clazz.getConstructor().newInstance();
+        // TODO 1: 用 Class.forName("course.Student") 拿 Class,getConstructor().newInstance() 创建对象
 
 
         // ② 获取私有属性 name 的 Field 对象
         // ② 获取私有属性 name 的 Field 对象
-        // TODO 1: Field fieldName = clazz.getDeclaredField("???");
-        Field fieldName = clazz.getDeclaredField("name");
+        // TODO 2: Field fieldName = clazz.getDeclaredField("???");   // ??? 填属性名
 
 
         // ③ 放开私有访问权限(暴力反射的关键一步!)
         // ③ 放开私有访问权限(暴力反射的关键一步!)
-        fieldName.setAccessible(true);   // TODO 2: 解释这行代码的作用
+        // TODO 3: 调用 fieldName.setAccessible(true)
 
 
         // ④ 给私有属性 name 赋值
         // ④ 给私有属性 name 赋值
-        fieldName.set(obj, "张三");      // TODO 3: field.set(对象, 值) 的含义
-
-        // TODO 4: 依次给 id(1001)、age(20)、gender("男") 赋值
-        Field fieldId = clazz.getDeclaredField("id");
-        fieldId.setAccessible(true);
-        fieldId.set(obj, 1001);
-
-        Field fieldAge = clazz.getDeclaredField("age");
-        fieldAge.setAccessible(true);
-        fieldAge.set(obj, 20);
+        // TODO 4: 调用 fieldName.set(obj, "张三")
 
 
-        Field fieldGender = clazz.getDeclaredField("gender");
-        fieldGender.setAccessible(true);
-        fieldGender.set(obj, "男");
+        // ⑤ 依次给 id(1001)、age(20)、gender("男") 赋值
+        // TODO 5: 参照上面 name 的写法(getDeclaredField + setAccessible + set),
+        //         分别获取 id/age/gender 三个字段并赋值
 
 
-        // ⑤ 用 field.get(obj) 读取属性值打印验证
-        System.out.println("id = " + fieldId.get(obj));
-        System.out.println("name = " + fieldName.get(obj));
-        System.out.println("age = " + fieldAge.get(obj));
-        System.out.println("gender = " + fieldGender.get(obj));
+        // ⑥ 用 field.get(obj) 读取属性值打印验证
+        // TODO 6: 用 fieldId.get(obj)、fieldName.get(obj) 等读取 4 个属性值并打印,格式参考"输出示例"
 
 
-        //  调用方法观察输出
-        ((Student) obj).study();
+        // ⑦ 调用方法观察输出
+        // TODO 7: 强转 ((Student) obj).study();
     }
     }
 }
 }
 ```
 ```
@@ -224,30 +198,24 @@ import java.lang.reflect.Method;
 
 
 public class ReflectInvokeMethodTest {
 public class ReflectInvokeMethodTest {
     public static void main(String[] args) throws Exception {
     public static void main(String[] args) throws Exception {
-        // ① 反射创建对象 + 反射给 name 赋值(复用练习二)
-        Class<?> clazz = Class.forName("course.Student");
-        Object obj = clazz.getConstructor().newInstance();
-        java.lang.reflect.Field fieldName = clazz.getDeclaredField("name");
-        fieldName.setAccessible(true);
-        fieldName.set(obj, "张三");
+        // ① 反射创建对象 + 反射给 name 赋值(复用练习一、二)
+        // TODO 1: 用 Class.forName("course.Student") 拿 Class,getConstructor().newInstance() 创建对象
+        // TODO 2: 用反射给私有属性 name 赋值为 "张三"(getDeclaredField + setAccessible(true) + set)
 
 
         // ② 获取 study 方法对象(无参数)
         // ② 获取 study 方法对象(无参数)
-        // TODO 1: Method studyMethod = clazz.getMethod("???");
-        Method studyMethod = clazz.getMethod("study");
+        // TODO 3: Method studyMethod = clazz.getMethod("???");   // ??? 填方法名
 
 
         // ③ 反射调用无参方法
         // ③ 反射调用无参方法
-        studyMethod.invoke(obj);   // TODO 2: method.invoke(对象) 的含义
+        // TODO 4: 用 studyMethod.invoke(obj) 调用方法
 
 
         // ④ 获取带 String 参数的 sayHello 方法
         // ④ 获取带 String 参数的 sayHello 方法
-        // TODO 3: Method sayHelloMethod = clazz.getMethod("sayHello", ???);
-        Method sayHelloMethod = clazz.getMethod("sayHello", String.class);
+        // TODO 5: Method sayHelloMethod = clazz.getMethod("sayHello", ???);   // ??? 填参数类型
 
 
         // ⑤ 反射调用带参方法,接收返回值
         // ⑤ 反射调用带参方法,接收返回值
-        // TODO 4: Object result = sayHelloMethod.invoke(对象, 参数);
-        Object result = sayHelloMethod.invoke(obj, "李四");
+        // TODO 6: Object result = sayHelloMethod.invoke(obj, "李四");
 
 
         // ⑥ 打印返回值
         // ⑥ 打印返回值
-        System.out.println("sayHello 返回:" + result);
+        // TODO 7: System.out.println("sayHello 返回:" + result);
     }
     }
 }
 }
 ```
 ```
@@ -313,32 +281,24 @@ import java.util.Properties;
 public class ReflectFrameWorkTest {
 public class ReflectFrameWorkTest {
     public static void main(String[] args) throws Exception {
     public static void main(String[] args) throws Exception {
         // ① 加载配置文件(回顾 Demo03:类加载器加载资源文件)
         // ① 加载配置文件(回顾 Demo03:类加载器加载资源文件)
-        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
-        InputStream is = classLoader.getResourceAsStream("student.properties");
-        Properties pro = new Properties();
-        pro.load(is);
-        is.close();
+        // TODO 1: 用 ClassLoader.getSystemClassLoader().getResourceAsStream("student.properties") 获取输入流
+        // TODO 2: 创建 Properties 对象,load(输入流) 解析,然后关闭流
 
 
-        // ② 从配置读取:类名 / 属性名+属性值 / 方法名(TODO 全部从配置文件读取,不要写死!)
-        String className = pro.getProperty("student.className");   // TODO 1: 读类名
-        String name = pro.getProperty("student.name");             // TODO 2: 读属性值
-        String methodName = pro.getProperty("student.methodName"); // TODO 3: 读方法名
+        // ② 从配置读取:类名 / 属性值 / 方法名(全部从配置文件读取,不要写死!)
+        // TODO 3: 用 pro.getProperty("student.className") / ("student.name") / ("student.methodName")
+        //         分别读取 className、name、methodName 三个值
 
 
         // ③ 反射:根据配置的类名加载类 + 创建对象(框架的核心动作!)
         // ③ 反射:根据配置的类名加载类 + 创建对象(框架的核心动作!)
-        Class<?> clazz = Class.forName(className);        // TODO 4: 用配置的类名反射加载
-        Object obj = clazz.getConstructor().newInstance();
+        // TODO 4: 用 Class.forName(className) 反射加载类,getConstructor().newInstance() 创建对象
 
 
         // ④ 反射:给属性赋值(属性名、属性值都来自配置文件)
         // ④ 反射:给属性赋值(属性名、属性值都来自配置文件)
-        Field fieldName = clazz.getDeclaredField("name");
-        fieldName.setAccessible(true);
-        fieldName.set(obj, name);
+        // TODO 5: 用 getDeclaredField("name") + setAccessible(true) + set(obj, name) 给私有属性赋值
 
 
         // ⑤ 反射:调用方法(方法名来自配置文件)
         // ⑤ 反射:调用方法(方法名来自配置文件)
-        Method method = clazz.getMethod(methodName);      // TODO 5: 用配置的方法名获取
-        method.invoke(obj);
+        // TODO 6: 用 getMethod(methodName) 获取方法,invoke(obj) 调用
 
 
         // ⑥ 打印创建的对象,验证属性已赋值
         // ⑥ 打印创建的对象,验证属性已赋值
-        System.out.println(obj);
+        // TODO 7: System.out.println(obj);
     }
     }
 }
 }
 ```
 ```