فهرست منبع

docs: 更新20260729课堂笔记,同步代码变更——新增泛型(Generics)完整章节:泛型概念与好处、定义格式(单类型/多类型/有界类型)、通配符(? / ? extends T)、自定义泛型类PrintX\<X\>、练习参考答案(Student重写toString/equals/hashCode、泛型vs原始类型)

WanJL 5 ساعت پیش
والد
کامیت
14794bf8aa

+ 2 - 2
README.md

@@ -34,7 +34,7 @@
 | 2026-07-24 | [多态 + 多态中的转型 + 内部类:多态概念与前提、多态成员访问特点、向上转型/向下转型、instanceof类型判断、多态的好处(开闭原则)、抽象类与多态结合(Animal→Dog;Person→Student/Teacher综合案例)、Usb接口多态案例(NoteBook接入鼠标/猫)、内部类概念与使用场景、成员内部类、私有内部类设计原则](./课堂笔记/01-JavaSE基础-笔记/20260724-笔记.md) |
 | 2026-07-27 | [匿名内部类 + Java API 与 String 类 + Math + 日期时间:内部类三大分类、匿名内部类四种使用方式、综合案例(USB/餐具/学生排序/计算器/动物叫声);API概念、String内存模型/不可变性/可变字符串StringBuffer&StringBuilder/文本块TextBlock JDK15+/String常用方法大全;Math数学类常用方法;日期时间类(Date/LocalDate/LocalTime/LocalDateTime/DateTimeFormatter)](./课堂笔记/01-JavaSE基础-笔记/20260727-笔记.md) |
 | 2026-07-28 | [Java 异常处理:异常概念、Throwable 体系结构、编译期/运行时异常、JVM 默认处理、try-catch 多 catch 块、异常常用方法、finally 资源关闭、throws 抛出、鲁棒性;自定义异常、throw/throws;Object 类:equals/hashCode/toString 重写、Objects 工具类;课后作业回顾 — String 分割去重/统计、LocalDate 天数差计算](./课堂笔记/01-JavaSE基础-笔记/20260728-笔记.md) |
-| 2026-07-29 | [包装类(Wrapper Classes)+ 集合框架入门(Collection Framework):基本类型与包装类对应关系、装箱与拆箱、自动装箱/拆箱、包装类优势、缓存机制、Bean 类应用;集合 vs 数组、体系结构(Collection/List/Set/Map)、线性表数据结构(栈/队列/数组/链表)、ArrayList 底层实现详解(默认容量10、扩容机制、三个构造方法、size vs capacity)、ArrayList 扩容方法(trimToSize / ensureCapacity / grow 1.5倍扩容公式)、位运算符 >> << 在扩容中的应用](./课堂笔记/01-JavaSE基础-笔记/20260729-笔记.md) |
+| 2026-07-29 | [包装类(Wrapper Classes)+ 集合框架入门(Collection Framework)+ 泛型(Generics):基本类型与包装类对应关系、装箱与拆箱、自动装箱/拆箱、包装类优势、缓存机制、Bean 类应用;集合 vs 数组、体系结构(Collection/List/Set/Map)、线性表数据结构(栈/队列/数组/链表)、ArrayList 底层实现详解(默认容量10、扩容机制、三个构造方法、size vs capacity、trimToSize/ensureCapacity/grow 1.5倍扩容公式、位运算符 >> <<)、ArrayList 常用方法速查;泛型概念与好处、泛型定义格式、通配符 ? / ? extends T、自定义泛型类、有界类型参数、练习参考答案(Student toString/equals/hashCode、泛型 vs 原始类型)](./课堂笔记/01-JavaSE基础-笔记/20260729-笔记.md) |
 
 ## 二、授课代码
 
@@ -55,7 +55,7 @@
 | 2026-07-24 | 多态概念与前提、多态成员访问特点、向上转型/向下转型、instanceof运算符、多态的好处(开闭原则)、抽象类+多态(Animal→Dog、Person→Student/Teacher→Test03.runPerson())、接口多态(Usb→Mouse/Cat→NoteBook)、内部类概念与使用场景 | `c260724` | [`course/polymorphism`](./授课代码/c260724/src/course/polymorphism/) / [`course/internalClass`](./授课代码/c260724/src/course/internalClass/) |
 | 2026-07-27 | 匿名内部类:内部类三大分类概念回顾、匿名内部类语法格式与本质、三种使用方式(多态接收变量赋值 / 方法参数传递 / 匿名对象直接调用)、配套接口/抽象类定义(Usb / Tableware / Compute / Sort)、综合案例(NoteBook USB设备 / Person 餐具 / 学生排序比较 / Calculator计算器 / Animal动物叫声);Java API:API概念、String类(内存模型/构造方法/==与equals/常用方法大全/不可变性)、可变字符串(StringBuffer/SringBuilder)、文本块TextBlock JDK15+;Math数学类;日期时间类(Date/LocalDate/LocalTime/LocalDateTime/DateTimeFormatter) | `c260727` | [`course/anonymousInternalClass`](./授课代码/c260727/src/course/anonymousInternalClass/) / [`course/api`](./授课代码/c260727/src/course/api/) / [`course/api/string`](./授课代码/c260727/src/course/api/string/) / [`course/api/math`](./授课代码/c260727/src/course/api/math/) / [`course/api/date`](./授课代码/c260727/src/course/api/date/) / [`exercise/exercise01`](./授课代码/c260727/src/exercise/exercise01/) / [`exercise/exercise06`](./授课代码/c260727/src/exercise/exercise06/) / [`exercise/exercise07`](./授课代码/c260727/src/exercise/exercise07/) / [`homework_0724/p2_myarray`](./授课代码/c260727/src/homework_0724/p2_myarray/) |
 | 2026-07-28 | 异常处理(Demo01~Demo04 + Person+AgeOutOfBoundsException) + Object类(Demo01+Person 重写equals/hashCode/toString) + 课后作业回顾(String工具 + 日期数学) + Exercises | `c260728` | [`course/api`](./授课代码/c260728/src/course/api/) / [`course/exception`](./授课代码/c260728/src/course/exception/) / [`homework260727`](./授课代码/c260728/src/homework260727/) / [`exercise/exercise01`](./授课代码/c260728/src/exercise/exercise01/) / [`exercise/exercise07`](./授课代码/c260728/src/exercise/exercise07/) |
-| 2026-07-29 | 包装类(Wrapper Classes):装箱与拆箱、自动装箱/拆箱、包装类在 Bean 类中的应用(Person + Demo01) + 集合框架入门(Collection Framework):集合 vs 数组、体系结构(Collection/List/Set/Map)、线性表数据结构(栈/队列/数组/链表)、ArrayList 底层实现详解(默认容量10、扩容机制、三个构造方法、size vs capacity、trimToSize/ensureCapacity/grow 1.5倍扩容公式、位移运算符 >> 与 <<) | `c260729` | [`course/packaging`](./授课代码/c260729/src/course/packaging/) / [`course/collection`](./授课代码/c260729/src/course/collection/) |
+| 2026-07-29 | 包装类 + 集合框架入门 + 泛型(Generics):装箱/拆箱、自动装箱/拆箱、包装类在 Bean 中的应用;集合 vs 数组、体系结构、线性表数据结构、ArrayList 底层实现详解(默认容量10、扩容机制、三个构造方法、size vs capacity、trimToSize/ensureCapacity/grow 1.5倍扩容公式、位移运算符)、ArrayList 常用方法速查;泛型概念与好处、定义格式、通配符、自定义泛型类、有界类型参数、练习参考答案(Student 类重写 toString/equals/hashCode、泛型 vs 原始类型) | `c260729` | [`course/packaging`](./授课代码/c260729/src/course/packaging/) / [`course/collection`](./授课代码/c260729/src/course/collection/) / [`exercises/exercise01`](./授课代码/c260729/src/exericse/exericse01/) / [`exercises/exercise02`](./授课代码/c260729/src/exericse/exericse02/) |
 
 ## 三、课堂练习题
 

+ 90 - 0
授课代码/c260729/src/course/collection/Demo03.java

@@ -0,0 +1,90 @@
+package course.collection;
+
+import course.packaging.Person;
+
+import java.util.ArrayList;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Demo03
+ * @description 泛型
+ * @create 2026/7/29
+ */
+public class Demo03 {
+    /*
+        Java中的泛型是JDK1.5引入的特性,它提供了编译时进行类型安全检测的机制
+        比如:
+        Person p=new Person();
+        Student s=new Student();
+        Dog d=new Dog();
+        ArrayList list=new ArrayList();
+        list.add(p);
+        list.add(s);
+        list.add(d);
+
+        //现在需要遍历集合,然后使用Person类型的work()方法
+
+        前两个元素可能会没问题,但是第三个元素,就可能出现类型转换异常。
+
+        泛型的好处:
+            把运行期间的问题,提前到了编译期间
+            避免了强制类型转换
+        泛型的定义格式:
+        <类型>    :   指定一种类型的格式,尖括号里面可以写任意字母单词都可以,一般我们只写一个字母,比如<E>、<T>
+        比如:
+        public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{}
+        使用的就是<E> 表示这个ArrayList要指定的类型。
+
+        比如:
+            public class MyArray<A>{
+                public void add(A a){
+                    ....
+                }
+            }
+        当使用MyArray的时候,直接传入指定的类型就可以了
+            MyArray<Integer> arr=new MyArray();
+            arr.add(必须是整数);
+
+
+            MyArray<String> arr=new MyArray();
+            arr.add(必须是字符串);
+            MyArray<Person> arr=new MyArray();
+            arr.add(new Person());
+
+
+        比如:
+            public class Compute<N>{
+                public N add(N n1,N n2){
+                    return n1+n2;
+                }
+            }
+            Compute<Double> c=new Compute();
+            c.add(3.14,3.16);
+
+        泛型定义的时候,除了指定一种类型,还可以指定多种类型, 只不过中间使用,分隔
+        比如:
+            <类型1,类型2,...类型n>    : 指定多种类型的格式,多种类型直接使用逗号隔开。
+        比如:
+            <K,V>   <E,T>   <A,B>.....
+
+        如果在定义泛型的时候,想要规定泛型的范围,可以:
+        <T extends 某个父类>        那么在使用泛型的时候,传入的类型只能是该父类的子类
+
+        ? 无界通配符         public void printList(List<?> list)
+        ? extends T    上界通配符        public void printList(List<? extends Person> list)
+
+
+     */
+    public static void main(String[] args) {
+        ArrayList<String> list=new ArrayList<>();
+        list.add("张三");
+        list.add("李四");
+        list.add("666");
+
+
+    }
+
+
+
+}

+ 27 - 0
授课代码/c260729/src/course/collection/PrintX.java

@@ -0,0 +1,27 @@
+package course.collection;
+
+import java.util.List;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Compute
+ * @description
+ * @create 2026/7/29
+ */
+public class PrintX<X> {
+
+    public void print(X x){
+        System.out.println(x.toString());
+    }
+
+    public X getX(X x){
+        return x;
+    }
+
+
+    public void printList(List<?> list){
+
+    }
+
+}

+ 26 - 0
授课代码/c260729/src/course/collection/Test.java

@@ -0,0 +1,26 @@
+package course.collection;
+
+import course.packaging.Person;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Test
+ * @description
+ * @create 2026/7/29
+ */
+public class Test {
+    public static void main(String[] args) {
+        PrintX<Person> px=new PrintX<>();
+        Person person = new Person();
+        person.setAge(25);
+        person.setName("张三");
+
+        ArrayList<Person> list=new ArrayList<>();
+        px.printList(list);
+
+    }
+}

+ 90 - 0
授课代码/c260729/src/exericse/exericse01/Student.java

@@ -0,0 +1,90 @@
+package exericse.exericse01;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Student
+ * @description 学生类
+ * @create 2026/7/29
+ */
+public class Student {
+    // 属性
+    private String name;      // 姓名
+    private Integer age;      // 年龄(使用包装类)
+    private String studentId; // 学号
+
+    /**
+     * 无参构造方法
+     */
+    public Student() {
+    }
+
+    /**
+     * 全参构造方法
+     * @param name 姓名
+     * @param age 年龄
+     * @param studentId 学号
+     */
+    public Student(String name, Integer age, String studentId) {
+        this.name = name;
+        this.age = age;
+        this.studentId = studentId;
+    }
+
+    // ========== Getter 和 Setter 方法 ==========
+
+    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 getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(String studentId) {
+        this.studentId = studentId;
+    }
+
+    /**
+     * 重写 toString 方法,方便打印对象信息
+     */
+    @Override
+    public String toString() {
+        return "Student{" +
+                "name='" + name + '\'' +
+                ", age=" + age +
+                ", studentId='" + studentId + '\'' +
+                '}';
+    }
+
+    /**
+     * 重写 equals 方法,基于学号判断两个学生是否相等
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null || getClass() != obj.getClass()) return false;
+        Student student = (Student) obj;
+        return studentId != null && studentId.equals(student.studentId);
+    }
+
+    /**
+     * 重写 hashCode 方法,基于学号生成哈希值
+     */
+    @Override
+    public int hashCode() {
+        return studentId != null ? studentId.hashCode() : 0;
+    }
+}

+ 43 - 0
授课代码/c260729/src/exericse/exericse01/StudentManager.java

@@ -0,0 +1,43 @@
+package exericse.exericse01;
+
+import java.util.ArrayList;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title StudentManager
+ * @description
+ * @create 2026/7/29
+ */
+public class StudentManager {
+    public static void main(String[] args) {
+        // 1. 创建一个 ArrayList,用于存储 Student 对象
+        //    提示:ArrayList<Student> students = new ArrayList<>();
+        ArrayList<Student> students = new ArrayList<>();
+        // 2. 创建 4 个 Student 对象,信息如下:
+        //    张三, 20, S001
+        //    李四, 21, S002
+        //    王五, 19, S003
+        //    赵六, 22, S004
+        Student stu1 = new Student("张三", 20, "S001");
+        Student stu2 = new Student("李四", 21, "S002");
+        Student stu3 = new Student("王五", 19, "S003");
+        Student stu4 = new Student("赵六", 22, "S004");
+
+        // 3. 将 4 个学生对象添加到 ArrayList 中
+        students.add(stu1);
+        students.add(stu2);
+        students.add(stu3);
+        students.add(stu4);
+
+        // 4. 输出 ArrayList 中的学生总数(使用 size() 方法)
+        System.out.println("学生总数:"+students.size());
+        // 5. 遍历 ArrayList,打印每个学生的信息(使用 for 循环 + get() 方法)
+        //    输出格式:学号:S001, 姓名:张三, 年龄:20
+        for (int i = 0; i < students.size(); i++) {
+            Student student = students.get(i);
+            System.out.println(student);
+
+        }
+    }
+}

+ 90 - 0
授课代码/c260729/src/exericse/exericse02/Student.java

@@ -0,0 +1,90 @@
+package exericse.exericse02;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Student
+ * @description 学生类
+ * @create 2026/7/29
+ */
+public class Student {
+    // 属性
+    private String name;      // 姓名
+    private Integer age;      // 年龄(使用包装类)
+    private String studentId; // 学号
+
+    /**
+     * 无参构造方法
+     */
+    public Student() {
+    }
+
+    /**
+     * 全参构造方法
+     * @param name 姓名
+     * @param age 年龄
+     * @param studentId 学号
+     */
+    public Student(String name, Integer age, String studentId) {
+        this.name = name;
+        this.age = age;
+        this.studentId = studentId;
+    }
+
+    // ========== Getter 和 Setter 方法 ==========
+
+    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 getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(String studentId) {
+        this.studentId = studentId;
+    }
+
+    /**
+     * 重写 toString 方法,方便打印对象信息
+     */
+    @Override
+    public String toString() {
+        return "Student{" +
+                "name='" + name + '\'' +
+                ", age=" + age +
+                ", studentId='" + studentId + '\'' +
+                '}';
+    }
+
+    /**
+     * 重写 equals 方法,基于学号判断两个学生是否相等
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null || getClass() != obj.getClass()) return false;
+        Student student = (Student) obj;
+        return studentId != null && studentId.equals(student.studentId);
+    }
+
+    /**
+     * 重写 hashCode 方法,基于学号生成哈希值
+     */
+    @Override
+    public int hashCode() {
+        return studentId != null ? studentId.hashCode() : 0;
+    }
+}

+ 64 - 0
授课代码/c260729/src/exericse/exericse02/StudentManager.java

@@ -0,0 +1,64 @@
+package exericse.exericse02;
+
+import java.util.ArrayList;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title StudentManager
+ * @description
+ * @create 2026/7/29
+ */
+public class StudentManager {
+    public static void main(String[] args) {
+        ArrayList students = new ArrayList<>();
+        Student stu1 = new Student("张三", 20, "S001");
+        Student stu2 = new Student("李四", 21, "S002");
+        Student stu3 = new Student("王五", 19, "S003");
+        Student stu4 = new Student("赵六", 22, "S004");
+        students.add(stu1);
+        students.add(stu2);
+        students.add(stu3);
+        students.add(stu4);
+
+        // 1. 判断列表是否为空(使用 isEmpty()),输出结果
+        System.out.println(students.isEmpty()?"是空":"不是空");
+        // 2. 查询学号为 S003 的学生(遍历查找),输出其信息
+        for (int i = 0; i < students.size(); i++) {
+            Object o = students.get(i);
+            if (o instanceof Student s){
+                if (s.getStudentId().equals("S003")){
+                    System.out.println(s);
+                }
+            }
+        }
+        // 3. 修改学号为 S002 的学生姓名将"李四"改为"李思"
+        for (int i = 0; i < students.size(); i++) {
+            Object o = students.get(i);
+            if (o instanceof Student s){
+                if (s.getName().equals("李四")){
+                    s.setName("李思");
+                }
+            }
+        }
+        // 4. 删除学号为 S004 的学生(赵六)
+        for (int i = 0; i < students.size(); i++) {
+            Object o = students.get(i);
+            if (o instanceof Student s){
+                if (s.getStudentId().equals("S004")){
+                    students.remove(i);
+                }
+            }
+        }
+        // 5. 在索引 1 的位置插入一个新学生:孙七, 18, S005
+        students.add(1,new Student("孙七", 18, "S005"));
+        // 6. 再次遍历输出所有学生信息
+        for (Object s:students){
+            System.out.println(s);
+        }
+        // 7. 查看此时列表中学生总数
+
+        System.out.println("学生总数:"+students.size());
+
+    }
+}

+ 240 - 1
课堂笔记/01-JavaSE基础-笔记/20260729-笔记.md

@@ -426,7 +426,230 @@ list.clear();               // 清空
 
 ---
 
-## 三、随堂练习要点
+## 三、泛型(Generics)
+
+### 3.1 泛型的概念
+
+**泛型(Generics)** 是 JDK 1.5 引入的特性,它提供了**编译时进行类型安全检测**的机制。
+
+**为什么需要泛型?**
+
+在没有泛型之前,`ArrayList` 可以存储任意类型的对象:
+
+```java
+ArrayList list = new ArrayList();
+list.add(new Person());   // Person 对象
+list.add(new Student());  // Student 对象
+list.add(new Dog());      // Dog 对象
+
+// 遍历时,需要强制类型转换,容易发生 ClassCastException
+for (int i = 0; i < list.size(); i++) {
+    Person p = (Person) list.get(i); // 遍历到 Dog 时抛出异常!
+}
+```
+
+> 📄 来源:`collection/Demo03.java`
+
+### 3.2 泛型的好处
+
+1. **把运行期间的问题,提前到了编译期间** — 编译时就能发现类型不匹配
+2. **避免了强制类型转换** — 编译器自动处理类型转换
+
+```java
+// 使用泛型后,编译时就能检查类型
+ArrayList<String> list = new ArrayList<>();
+list.add("张三");
+list.add("李四");
+// list.add(666);  // 编译报错!只能添加 String 类型
+
+// 遍历时无需强制类型转换
+for (int i = 0; i < list.size(); i++) {
+    String s = list.get(i);  // 自动识别为 String 类型
+}
+```
+
+> 📄 来源:`collection/Demo03.java`
+
+### 3.3 泛型的定义格式
+
+#### 单类型参数
+
+```java
+<类型>   // 如 <E>、<T>,尖括号里面可以写任意字母,一般只写一个字母
+```
+
+`ArrayList` 的源码定义:
+
+```java
+public class ArrayList<E> extends AbstractList<E>
+    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
+    // 使用的就是 <E> 表示这个 ArrayList 要操作的元素类型
+}
+```
+
+#### 自定义泛型类
+
+```java
+public class MyArray<A> {
+    public void add(A a) {
+        // ... 传入的类型由使用时决定
+    }
+}
+
+// 使用:
+MyArray<Integer> arr1 = new MyArray<>();
+arr1.add(10);        // 必须是 Integer
+
+MyArray<String> arr2 = new MyArray<>();
+arr2.add("Hello");   // 必须是 String
+```
+
+**完整示例** — `PrintX<X>` 泛型类:
+
+```java
+public class PrintX<X> {
+    public void print(X x) {
+        System.out.println(x.toString());
+    }
+
+    public X getX(X x) {
+        return x;
+    }
+
+    public void printList(List<?> list) {
+        // 使用无界通配符 ?
+    }
+}
+
+// 使用:
+PrintX<Person> px = new PrintX<>();
+Person person = new Person();
+person.setAge(25);
+person.setName("张三");
+px.print(person);  // 输出 Person 对象的 toString()
+```
+
+> 📄 来源:`collection/PrintX.java`、`collection/Test.java`
+
+#### 多类型参数
+
+可以指定多种类型,中间使用逗号分隔:
+
+```java
+<类型1, 类型2, ..., 类型n>
+
+// 例如:
+<K,V>   <E,T>   <A,B>
+```
+
+### 3.4 泛型的通配符(Wildcard)
+
+| 通配符 | 名称 | 说明 | 示例 |
+|--------|------|------|------|
+| `?` | **无界通配符**(Unbounded Wildcard) | 表示未知类型,可以接收任意类型 | `public void printList(List<?> list)` |
+| `? extends T` | **上界通配符**(Upper Bounded Wildcard) | 表示类型是 T 或 T 的子类 | `public void printList(List<? extends Person> list)` |
+| `? super T` | **下界通配符**(Lower Bounded Wildcard) | 表示类型是 T 或 T 的父类 | `public void add(List<? super Integer> list)` |
+
+```java
+// 无界通配符
+public void printList(List<?> list) {
+    for (Object obj : list) {
+        System.out.println(obj);
+    }
+}
+
+// 上界通配符 — 只允许 Person 及其子类
+public void processPersons(List<? extends Person> list) {
+    for (Person p : list) {
+        System.out.println(p.getName());
+    }
+}
+```
+
+> 📄 来源:`collection/Demo03.java`
+
+### 3.5 有界类型参数(Bounded Type Parameter)
+
+使用 `extends` 关键字限制泛型的类型范围:
+
+```java
+<T extends 某个父类>
+// 使用时,传入的类型只能是该父类的子类
+```
+
+```java
+public class GenericMethod {
+    // 只允许 Number 及其子类(Integer、Double 等)
+    public static <T extends Number> double sum(T a, T b) {
+        return a.doubleValue() + b.doubleValue();
+    }
+}
+
+// 使用:
+double result = GenericMethod.sum(10, 20);    // Integer ✓
+double result2 = GenericMethod.sum(3.14, 2.5); // Double ✓
+// GenericMethod.sum("A", "B");  // 编译报错!String 不是 Number 的子类
+```
+
+### 3.6 泛型在集合中的实际应用
+
+```java
+// 带泛型的 ArrayList
+ArrayList<String> list1 = new ArrayList<>();     // 只能存 String
+ArrayList<Person> list2 = new ArrayList<>();     // 只能存 Person
+ArrayList<Integer> list3 = new ArrayList<>();    // 只能存 Integer
+
+// LinkedList 同样支持泛型
+LinkedList<Person> linkedList = new LinkedList<>();
+```
+
+> 📄 来源:`collection/Test.java`
+
+### 3.7 课堂练习代码参考
+
+课程配套的两个练习参考答案,展示了 Student 类的完整实现:
+
+**Student 类** — 重写了 `toString()`、`equals()`、`hashCode()` 方法:
+
+| 方法 | 用途 |
+|------|------|
+| `toString()` | 方便打印学生信息 |
+| `equals(Object)` | 基于学号判断两个学生是否相等 |
+| `hashCode()` | 基于学号生成哈希值 |
+
+```java
+// equals() 方法 — 基于学号比较
+@Override
+public boolean equals(Object obj) {
+    if (this == obj) return true;
+    if (obj == null || getClass() != obj.getClass()) return false;
+    Student student = (Student) obj;
+    return studentId != null && studentId.equals(student.studentId);
+}
+```
+
+> 📄 来源:`exercises/exercise01/Student.java`、`exercises/exercise02/Student.java`
+
+**注意**:`exercise02` 中的 `StudentManager` 使用了**未使用泛型**的原始类型写法:
+
+```java
+ArrayList students = new ArrayList<>();  // 未指定泛型
+// 遍历时需要通过 instanceof 进行类型判断
+for (int i = 0; i < students.size(); i++) {
+    Object o = students.get(i);
+    if (o instanceof Student s) {  // JDK 16+ 模式匹配
+        System.out.println(s);
+    }
+}
+```
+
+> 💡 **对比**:`exercise01` 使用了泛型 `ArrayList<Student>`,`exercise02` 使用原始类型。推荐始终使用泛型以享受编译时类型检查的好处。
+
+> 📄 来源:`exercises/exercise01/StudentManager.java`、`exercises/exercise02/StudentManager.java`
+
+---
+
+## 四、随堂练习要点
 
 ### 本日课程知识点概览
 
@@ -441,6 +664,11 @@ list.clear();               // 清空
 | **ArrayList 扩容方法** | **trimToSize 缩减容量、ensureCapacity 手动扩容、grow 1.5倍扩容公式** | `collection/Demo02.java` |
 | **位运算符** | **`>>` 右移(除2)、`<<` 左移(乘2)在扩容中的使用** | `collection/Demo02.java` |
 | **ArrayList 常用方法** | **add/get/set/remove/size/isEmpty/contains/indexOf/toArray/getFirst/getLast** | `collection/Demo02.java` |
+| **泛型(Generics)概念** | **编译时类型安全检测、避免强制类型转换** | `collection/Demo03.java` |
+| **泛型定义格式** | **单类型 `<E>`、多类型 `<K,V>`、有界类型 `<T extends 父类>`** | `collection/Demo03.java` |
+| **泛型通配符** | **`?` 无界通配符、`? extends T` 上界通配符** | `collection/Demo03.java` |
+| **自定义泛型类** | **PrintX\<X\>、print(X x)、getX(X x)、printList(List\<?\>)** | `collection/PrintX.java` |
+| **练习参考答案** | **Student 类重写 toString/equals/hashCode、泛型 vs 原始类型对比** | `exercise01/*.java`、`exercise02/*.java` |
 
 ### 包装类重点
 
@@ -452,6 +680,14 @@ list.clear();               // 清空
    - 包装类对象参与算术运算时的自动拆箱
    - `null` 包装类拆箱会抛出 `NullPointerException`
 
+### 泛型重点
+
+1. **理解泛型的必要性**:解决了原始集合类型不安全、需要强制类型转换的问题
+2. **区分三种通配符**:`?`(无界)、`? extends T`(上界)、`? super T`(下界)
+3. **掌握泛型定义语法**:`<T>`、`<K,V>`、`<T extends 父类>`
+4. **泛型 VS 原始类型**:始终优先使用泛型(`ArrayList<Student>`),避免原始类型
+5. **模式匹配 instanceof**:JDK 16+ 支持 `if (o instanceof Student s)` 自动变量绑定
+
 ### 集合框架重点
 
 1. **理解集合 vs 数组的区别**:长度可变性、元素类型限制
@@ -477,5 +713,8 @@ list.clear();               // 清空
 - [Java 包装类缓存机制详解](https://www.baeldung.com/java-integer-cache)
 - [Oracle Java 官方文档 — Collections Framework Overview](https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html)
 - [Java 集合框架详解:List、Set、Map 的区别](https://www.baeldung.com/java-collections)
+- [Oracle Java 官方文档 — Generics Tutorial](https://docs.oracle.com/javase/tutorial/java/generics/index.html)
+- [Java 泛型:通配符详解](https://www.baeldung.com/java-generics-advanced)
 - 《Java 核心技术 卷I》第 3 章 — 包装器类与自动装箱
+- 《Java 核心技术 卷I》第 5 章 — 泛型
 - 《Java 核心技术 卷I》第 9 章 — 集合