Browse Source

docs: 更新20260724课堂笔记,同步代码变更——新增内部类(概念/使用场景/成员内部类/私有内部类设计原则)、多态代码移入course.polymorphism子包、新增exercise04练习答案

WanJL 10 hours ago
parent
commit
dc383e4a4c
27 changed files with 666 additions and 31 deletions
  1. 2 2
      README.md
  2. 108 0
      授课代码/c260724/src/course/internalClass/Demo01.java
  3. 11 0
      授课代码/c260724/src/course/internalClass/Heart.java
  4. 12 0
      授课代码/c260724/src/course/internalClass/Person.java
  5. 23 0
      授课代码/c260724/src/course/internalClass/Test01.java
  6. 1 1
      授课代码/c260724/src/course/polymorphism/Animal.java
  7. 1 1
      授课代码/c260724/src/course/polymorphism/Cat.java
  8. 1 1
      授课代码/c260724/src/course/polymorphism/Demo01.java
  9. 1 1
      授课代码/c260724/src/course/polymorphism/Demo02.java
  10. 1 1
      授课代码/c260724/src/course/polymorphism/Dog.java
  11. 1 1
      授课代码/c260724/src/course/polymorphism/Mouse.java
  12. 1 1
      授课代码/c260724/src/course/polymorphism/NoteBook.java
  13. 1 1
      授课代码/c260724/src/course/polymorphism/Person.java
  14. 1 1
      授课代码/c260724/src/course/polymorphism/Student.java
  15. 1 1
      授课代码/c260724/src/course/polymorphism/Teacher.java
  16. 1 1
      授课代码/c260724/src/course/polymorphism/Test01.java
  17. 1 1
      授课代码/c260724/src/course/polymorphism/Test02.java
  18. 1 1
      授课代码/c260724/src/course/polymorphism/Test03.java
  19. 1 1
      授课代码/c260724/src/course/polymorphism/Usb.java
  20. 0 0
      授课代码/c260724/src/course/polymorphism/img.png
  21. 48 0
      授课代码/c260724/src/exercise/exercise04/Employee.java
  22. 63 0
      授课代码/c260724/src/exercise/exercise04/EmployeeManager.java
  23. 43 0
      授课代码/c260724/src/exercise/exercise04/FullTimeEmployee.java
  24. 34 0
      授课代码/c260724/src/exercise/exercise04/Intern.java
  25. 43 0
      授课代码/c260724/src/exercise/exercise04/PartTimeEmployee.java
  26. 98 0
      授课代码/c260724/src/exercise/exercise04/题目.md
  27. 167 15
      课堂笔记/01-JavaSE基础-笔记/20260724-笔记.md

+ 2 - 2
README.md

@@ -31,7 +31,7 @@
 | 2026-07-21 | [构造方法:构造方法重载、this() 调用、private 构造方法、单例模式、课后作业回顾](./课堂笔记/01-JavaSE基础-笔记/20260721-笔记.md) |
 | 2026-07-22 | [继承:继承概念与格式、方法重写(@Override)、super 关键字、就近原则、继承中构造方法、单继承与多层继承、访问修饰符](./课堂笔记/01-JavaSE基础-笔记/20260722-笔记.md) |
 | 2026-07-23 | [抽象类 + final + 模板方法 + 代码块 + 接口(含JDK8+新特性):抽象类定义与特点、final 类/方法/变量、模板方法模式、三种代码块、接口定义与实现(Usb→LogiMouse/ROGMouse)、接口 vs 抽象类对比、JDK8默认方法static方法、JDK9私有方法](./课堂笔记/01-JavaSE基础-笔记/20260723-笔记.md) |
-| 2026-07-24 | [多态 + 多态中的转型:多态概念与前提、多态成员访问特点、向上转型/向下转型、instanceof类型判断、多态的好处(开闭原则)、抽象类与多态结合(Animal→Dog;Person→Student/Teacher综合案例)、Usb接口多态案例(NoteBook接入鼠标/猫)](./课堂笔记/01-JavaSE基础-笔记/20260724-笔记.md) |
+| 2026-07-24 | [多态 + 多态中的转型 + 内部类:多态概念与前提、多态成员访问特点、向上转型/向下转型、instanceof类型判断、多态的好处(开闭原则)、抽象类与多态结合(Animal→Dog;Person→Student/Teacher综合案例)、Usb接口多态案例(NoteBook接入鼠标/猫)、内部类概念与使用场景、成员内部类、私有内部类设计原则](./课堂笔记/01-JavaSE基础-笔记/20260724-笔记.md) |
 
 ## 二、授课代码
 
@@ -49,7 +49,7 @@
 | 2026-07-21 | 构造方法:构造方法重载、this() 调用、private 构造方法、单例模式、Fisher-Yates 洗牌算法、课后作业回顾 | `c260721` | [`course`](./授课代码/c260721/src/course/) / [`homework/c260717`](./授课代码/c260721/src/homework/c260717/) / [`homework/c260720`](./授课代码/c260721/src/homework/c260720/) / [`exercise/exercise01`](./授课代码/c260721/src/exercise/exercise01/) / [`exercise/exercise02`](./授课代码/c260721/src/exercise/exercise02/) |
 | 2026-07-22 | 继承:继承概念与格式、方法重写(Override)、super 关键字、就近原则、继承中构造方法、单继承与多层继承、访问修饰符、综合练习(学生管理系统+冒泡排序)、课后作业 | `c260722` | [`course`](./授课代码/c260722/src/course/) / [`exercise/studentSystem`](./授课代码/c260722/src/exercise/studentSystem/) / [`homework/p08_guessgame`](./授课代码/c260722/src/homework/p08_guessgame/) / [`homework/p09_bookmanager`](./授课代码/c260722/src/homework/p09_bookmanager/) |
 | 2026-07-23 | 抽象类 + final + 模板方法 + 代码块 + 接口(含JDK8+新特性):抽象类定义与特点、final 类/方法/变量、模板方法模式(MyOneDayTemplate)、三种代码块(局部/构造/静态)、接口定义与实现(Usb→LogiMouse/ROGMouse)、接口 vs 抽象类对比、JDK8默认方法/静态方法(MyDefaultInterface→MyDefaultInterfaceImpl)、JDK9私有方法(抽取多个默认方法公共代码)、Test05 测试类 | `c260723` | [`course`](./授课代码/c260723/src/course/) |
-| 2026-07-24 | 多态概念与前提、多态成员访问特点、向上转型/向下转型、instanceof运算符、多态的好处(开闭原则)、抽象类+多态(Animal→Dog、Person→Student/Teacher→Test03.runPerson())、接口多态(Usb→Mouse/Cat→NoteBook) | `c260724` | [`course`](./授课代码/c260724/src/course/) |
+| 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/) |
 
 ## 三、课堂练习题
 

+ 108 - 0
授课代码/c260724/src/course/internalClass/Demo01.java

@@ -0,0 +1,108 @@
+package course.internalClass;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Demo01
+ * @description 内部类
+ * @create 2026/7/24
+ */
+public class Demo01 {
+    /*
+    内部类:
+        在一个类中定义一个类,比如:在一个类A的内部定义了一个类B,B类就是内部类。
+
+        什么样的场景会使用内部类,比如 一个类的 属性不能够更好描述 内部细节,比如
+        class 人类{
+            心脏;
+        }
+
+        class 汽车{
+            发动机;
+        }
+        这里 的心脏 和 发动机 都是依托于 人类 和汽车类存在的,但是只有一个属性不能更好表达心脏类和发动机类
+        因为发动机类 也应该有自己的属性和方法,所以要使用内部类
+    内部类的定义格式:
+        class 外部类名{
+            修饰符 class 内部类名{
+
+
+            }
+        }
+        比如:
+        class 汽车{
+            class 发动机{
+
+            }
+        }
+    内部类的特点:
+        1、内部类可以直接访问外部类的所有成员,包括私有化的。
+        2、外部类要访问内部类的成员,必须要创建对象。
+
+        public class Person{
+            private String name;
+            //这就是内部类
+            public class Heart{
+                public void jump(){
+                    //内部类可以直接调用外部类的所有成员
+                    System.out.println(name+"的心脏跳动....");
+                }
+            }
+            //外部类的方法
+            public void method(){
+                //外部类想访问内部类的成员,就需要创建内部类的对象
+                Heart h=new Heart();
+                h.jump();   //调用内部类的方法
+            }
+
+        }
+
+     内部类的划分:
+        1、成员内部类---存在于外部类的内部,属于外部类的成员,和成员变量、成员方法、代码块是同一层次
+           其他的类如果想要访问某类的内部类,就需要按照下面的格式来定义:
+            格式: 外部类名.内部类名 对象名 = new 外部类().new 内部类();
+            比如: Person.Heart h=new Person().new Heart();
+            成员内部类属于外部类的成员,所以也可以使用访问权限修饰符进行修饰,比如private。
+            如果使用private修饰的内部类。就不能被其他类访问了。
+            一般来讲,给一个类设计内部类的目的[其实就是不想让外界访问内部类,只想自己使用]。
+            所以内部类的定义就应该是私有化的,私有化之后,在提高一个让外界可以调用的方法,
+            方法的内部创建内部类的对象并且调用。
+
+            public class Heart {
+            }
+
+            public class Person {
+                Heart heart;
+            }
+            public class Test01 {
+                public static void main(String[] args) {
+                    Person person=new Person();
+                    person.heart=new Heart();
+
+                    //也就是说,想要访问心脏,需要先创建人的对象, 再创建心脏的对象。
+
+                    //但是也可以直接跳过人,直接创建心脏的对象
+                    Heart h=new Heart();
+
+                    //这种情况是不符合我们的现实业务逻辑的。所以要把Heart类设置为内部类。
+                    //并且提供一个可以让外部调用的方法,但是必须要通过Person,来调用
+                }
+            }
+
+            所以要使用内部类:
+            public class Person {
+                private class Heart {
+                }
+                public Heart getHeart(){
+                    return new Heart();
+                }
+            }
+            // 这才是合理的,需要先创建人的对象,在通过人对象调用getHeart()方法,创建这个人的心脏对象。
+
+     */
+
+
+
+
+
+}

+ 11 - 0
授课代码/c260724/src/course/internalClass/Heart.java

@@ -0,0 +1,11 @@
+package course.internalClass;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Heart
+ * @description
+ * @create 2026/7/24
+ */
+public class Heart {
+}

+ 12 - 0
授课代码/c260724/src/course/internalClass/Person.java

@@ -0,0 +1,12 @@
+package course.internalClass;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Person
+ * @description
+ * @create 2026/7/24
+ */
+public class Person {
+    Heart heart;
+}

+ 23 - 0
授课代码/c260724/src/course/internalClass/Test01.java

@@ -0,0 +1,23 @@
+package course.internalClass;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Test01
+ * @description
+ * @create 2026/7/24
+ */
+public class Test01 {
+    public static void main(String[] args) {
+        Person person=new Person();
+        person.heart=new Heart();
+
+        //也就是说,想要访问心脏,需要先创建人的对象, 再创建心脏的对象。
+
+        //但是也可以直接跳过人,直接创建心脏的对象
+        Heart h=new Heart();
+
+        //这种情况是不符合我们的现实业务逻辑的。所以要把Heart类设置为内部类。
+        //并且提供一个可以让外部调用的方法,但是必须要通过Person,来调用
+    }
+}

+ 1 - 1
授课代码/c260724/src/course/Animal.java → 授课代码/c260724/src/course/polymorphism/Animal.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Cat.java → 授课代码/c260724/src/course/polymorphism/Cat.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Demo01.java → 授课代码/c260724/src/course/polymorphism/Demo01.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Demo02.java → 授课代码/c260724/src/course/polymorphism/Demo02.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Dog.java → 授课代码/c260724/src/course/polymorphism/Dog.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Mouse.java → 授课代码/c260724/src/course/polymorphism/Mouse.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/NoteBook.java → 授课代码/c260724/src/course/polymorphism/NoteBook.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Person.java → 授课代码/c260724/src/course/polymorphism/Person.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Student.java → 授课代码/c260724/src/course/polymorphism/Student.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Teacher.java → 授课代码/c260724/src/course/polymorphism/Teacher.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Test01.java → 授课代码/c260724/src/course/polymorphism/Test01.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Test02.java → 授课代码/c260724/src/course/polymorphism/Test02.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Test03.java → 授课代码/c260724/src/course/polymorphism/Test03.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 1 - 1
授课代码/c260724/src/course/Usb.java → 授课代码/c260724/src/course/polymorphism/Usb.java

@@ -1,4 +1,4 @@
-package course;
+package course.polymorphism;
 
 /**
  * @author WanJl

+ 0 - 0
授课代码/c260724/src/course/img.png → 授课代码/c260724/src/course/polymorphism/img.png


+ 48 - 0
授课代码/c260724/src/exercise/exercise04/Employee.java

@@ -0,0 +1,48 @@
+package exercise.exercise04;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Employee
+ * @description
+ * @create 2026/7/24
+ */
+public abstract class Employee {
+    private int id;
+    private String name;
+
+    public Employee(int id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    /**
+     * 计算薪资
+     * @return
+     */
+    public abstract double calculateSalary();
+
+    /**
+     * 输出 "工号:xxx,姓名:xxx,薪资:xxx"(调用 calculateSalary() 获得薪资)
+     */
+    public void showInfo(){
+        System.out.println("工号:"+id+",姓名:"+name+",薪资:"+calculateSalary());
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}
+

+ 63 - 0
授课代码/c260724/src/exercise/exercise04/EmployeeManager.java

@@ -0,0 +1,63 @@
+package exercise.exercise04;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title EmployeeManager
+ * @description
+ * @create 2026/7/24
+ */
+public class EmployeeManager {
+    public static void main(String[] args) {
+        // 示例数据
+        Employee emp1 = new FullTimeEmployee(1001, "张三", 8000, 2000);
+        Employee emp2 = new PartTimeEmployee(2001, "李四", 50, 80);
+        Employee emp3 = new Intern(3001, "王五", 2000);
+        Employee emp4 = new FullTimeEmployee(1002, "赵六", 10000, 3000);
+        Employee emp5 = new PartTimeEmployee(2002, "孙七", 45, 60);
+
+        //1、创建员工数组:创建一个 Employee[] 数组,包含至少 5 名员工(各类型混合)
+        Employee[] employees={emp1,emp2,emp3,emp4,emp5};
+        //2、遍历数组输出基本信息:调用每个元素的 showInfo() 方法
+        for (int i = 0; i < employees.length; i++) {
+            Employee employee=employees[i];
+            employee.showInfo();
+        }
+        /*
+        3、遍历数组,按类型执行特有行为:
+            如果是 FullTimeEmployee → 向下转型 → 调用 attendMeeting()
+            如果是 PartTimeEmployee → 向下转型 → 调用 clockIn()
+            如果是 Intern → 向下转型 → 调用 learnSkill()
+         */
+        for (Employee e:employees){
+            if (e instanceof  FullTimeEmployee fte){
+                fte.attendMeeting();
+            } else if (e instanceof PartTimeEmployee pte) {
+                pte.clockIn();
+            } else if (e instanceof  Intern i) {
+                i.learnSkill();
+            }
+        }
+
+        //4、计算总薪资成本:遍历数组,累加所有员工的 calculateSalary(),输出总薪资
+        double sum=0;
+        for (Employee e:employees){
+            sum+=e.calculateSalary();
+        }
+        System.out.println("总薪资:"+sum);
+
+        //5、查找薪资最高的员工:遍历数组,找出 calculateSalary() 最大的员工,输出其信息
+
+
+        double max=employees[0].calculateSalary();  //设定 数组第1位员工的薪资为最高薪资。
+        int maxIndex=0;
+        for (int i=1; i < employees.length; i++) {
+            if (employees[i].calculateSalary()>max){
+                max=employees[i].calculateSalary();
+                maxIndex= i;
+            }
+        }
+        System.out.print("最高薪资员工是:");
+        employees[maxIndex].showInfo();
+    }
+}

+ 43 - 0
授课代码/c260724/src/exercise/exercise04/FullTimeEmployee.java

@@ -0,0 +1,43 @@
+package exercise.exercise04;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title FullTimeEmployee
+ * @description
+ * @create 2026/7/24
+ */
+public class FullTimeEmployee extends Employee{
+    private double baseSalary;
+    private double bonus;
+
+    /**
+     * 有参构造方法
+     * @param id 工号
+     * @param name 名称
+     * @param baseSalary 工资
+     * @param bonus 奖金
+     */
+    public FullTimeEmployee(int id, String name, double baseSalary, double bonus) {
+        super(id, name);
+        this.baseSalary = baseSalary;
+        this.bonus = bonus;
+    }
+
+    /**
+     * 计算薪资
+     * 返回 baseSalary + bonus * 1.2(绩效上浮 20%)
+     * @return
+     */
+    @Override
+    public double calculateSalary() {
+        return baseSalary+bonus*1.2;
+    }
+
+    /**
+     * 输出 "正式员工 xxx 参加周会..."(xxx 为姓名)
+     */
+    public void attendMeeting(){
+        System.out.println("正式员工 "+this.getName()+" 参加周会...");
+    }
+}

+ 34 - 0
授课代码/c260724/src/exercise/exercise04/Intern.java

@@ -0,0 +1,34 @@
+package exercise.exercise04;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Intern
+ * @description
+ * @create 2026/7/24
+ */
+public class Intern extends Employee{
+    private double allowance;
+
+    public Intern(int id, String name, double allowance) {
+        super(id, name);
+        this.allowance = allowance;
+    }
+
+    /**
+     * 计算薪资
+     *  返回 allowance(固定津贴,无其他扣减)
+     * @return
+     */
+    @Override
+    public double calculateSalary() {
+        return allowance;
+    }
+
+    /**
+     * 输出 "实习生 xxx 在学习新技能..."(xxx 为姓名)
+     */
+    public void learnSkill(){
+        System.out.println("实习生 "+this.getName()+" 在学习新技能...");
+    }
+}

+ 43 - 0
授课代码/c260724/src/exercise/exercise04/PartTimeEmployee.java

@@ -0,0 +1,43 @@
+package exercise.exercise04;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title PartTimeEmployee
+ * @description
+ * @create 2026/7/24
+ */
+public class PartTimeEmployee extends Employee{
+    private double hourlyRate;
+    private int hoursWorked;
+
+    /**
+     * 有参构造方法
+     * @param id 工号
+     * @param name 姓名
+     * @param hourlyRate 时薪
+     * @param hoursWorked 小时数
+     */
+    public PartTimeEmployee(int id, String name, double hourlyRate, int hoursWorked) {
+        super(id, name);
+        this.hourlyRate = hourlyRate;
+        this.hoursWorked = hoursWorked;
+    }
+
+    /**
+     * 计算薪资
+     * 返回 hourlyRate * hoursWorked
+     * @return
+     */
+    @Override
+    public double calculateSalary() {
+        return hourlyRate*hoursWorked;
+    }
+
+    /**
+     * 输出 "兼职员工 xxx 打卡上班..."(xxx 为姓名)
+     */
+    public void clockIn(){
+        System.out.println("兼职员工 "+this.getName()+" 打卡上班...");
+    }
+}

+ 98 - 0
授课代码/c260724/src/exercise/exercise04/题目.md

@@ -0,0 +1,98 @@
+## 第 1 题:多态 + 对象数组 + instanceof——员工绩效管理系统 ⭐⭐⭐⭐
+
+### 需求说明
+
+某公司有三种类型的员工:**正式员工**(全职)、**兼职员工**(按时计薪)和 **实习生**(固定津贴)。每种员工的薪资计算方式不同,且各有特有行为。
+
+使用 **多态数组** 存储所有员工,遍历时通过 `instanceof` 判断类型并向下转型,调用特有方法。
+
+### 类设计
+
+**`Employee` 抽象类**(父类):
+
+- **私有属性**:`id`(工号,int)、`name`(姓名,String)
+- **有参构造方法**:`Employee(int id, String name)`
+- **抽象方法**:`double calculateSalary()` —— 计算薪资
+- **普通方法**:`void showInfo()` —— 输出 `"工号:xxx,姓名:xxx,薪资:xxx"`(调用 `calculateSalary()` 获得薪资)
+
+**`FullTimeEmployee` 类**(继承 Employee):
+
+- **私有属性**:`baseSalary`(基本工资,double)、`bonus`(绩效奖金,double)
+- **构造方法**:`FullTimeEmployee(int id, String name, double baseSalary, double bonus)`
+- **重写** `calculateSalary()` —— 返回 `baseSalary + bonus * 1.2`(绩效上浮 20%)
+- **特有方法**:`void attendMeeting()` —— 输出 `"正式员工 xxx 参加周会..."`(xxx 为姓名)
+
+**`PartTimeEmployee` 类**(继承 Employee):
+
+- **私有属性**:`hourlyRate`(时薪,double)、`hoursWorked`(工作小时数,int)
+- **构造方法**:`PartTimeEmployee(int id, String name, double hourlyRate, int hoursWorked)`
+- **重写** `calculateSalary()` —— 返回 `hourlyRate * hoursWorked`
+- **特有方法**:`void clockIn()` —— 输出 `"兼职员工 xxx 打卡上班..."`(xxx 为姓名)
+
+**`Intern` 类**(继承 Employee):
+
+- **私有属性**:`allowance`(实习津贴,double)
+- **构造方法**:`Intern(int id, String name, double allowance)`
+- **重写** `calculateSalary()` —— 返回 `allowance`(固定津贴,无其他扣减)
+- **特有方法**:`void learnSkill()` —— 输出 `"实习生 xxx 在学习新技能..."`(xxx 为姓名)
+
+### 测试类要求
+
+**`EmployeeManager` 类**:
+
+1. **创建员工数组**:创建一个 `Employee[]` 数组,包含至少 5 名员工(各类型混合)
+
+   ```java
+   // 示例数据
+   Employee emp1 = new FullTimeEmployee(1001, "张三", 8000, 2000);
+   Employee emp2 = new PartTimeEmployee(2001, "李四", 50, 80);
+   Employee emp3 = new Intern(3001, "王五", 2000);
+   Employee emp4 = new FullTimeEmployee(1002, "赵六", 10000, 3000);
+   Employee emp5 = new PartTimeEmployee(2002, "孙七", 45, 60);
+   ```
+
+2. **遍历数组输出基本信息**:调用每个元素的 `showInfo()` 方法
+
+3. **遍历数组,按类型执行特有行为**:
+
+    - 如果是 `FullTimeEmployee` → 向下转型 → 调用 `attendMeeting()`
+    - 如果是 `PartTimeEmployee` → 向下转型 → 调用 `clockIn()`
+    - 如果是 `Intern` → 向下转型 → 调用 `learnSkill()`
+
+4. **计算总薪资成本**:遍历数组,累加所有员工的 `calculateSalary()`,输出总薪资
+
+5. **查找薪资最高的员工**:遍历数组,找出 `calculateSalary()` 最大的员工,输出其信息
+
+### 思考题
+
+1. `Employee[]` 数组中存储的是不同类型对象,这体现了面向对象哪个特征?
+2. 如果不用 `instanceof` 判断类型,直接向下转型会有什么风险?
+3. 如果新增一个 `Contractor`(外包人员)类,需要修改哪些代码?这些修改是否符合「开闭原则」?
+
+### 预期输出(参考)
+
+```
+========== 员工薪资信息 ==========
+工号:1001,姓名:张三,薪资:10400.00
+工号:2001,姓名:李四,薪资:4000.00
+工号:3001,姓名:王五,薪资:2000.00
+工号:1002,姓名:赵六,薪资:13600.00
+工号:2002,姓名:孙七,薪资:2700.00
+
+========== 执行特有行为 ==========
+正式员工 张三 参加周会...
+兼职员工 李四 打卡上班...
+实习生 王五 在学习新技能...
+正式员工 赵六 参加周会...
+兼职员工 孙七 打卡上班...
+
+========== 薪资统计 ==========
+总薪资成本:32700.00 元
+薪资最高的员工:工号:1002,姓名:赵六,薪资:13600.00
+```
+
+> **提示**:
+>
+> - 数组类型声明为 `Employee[]`,存储不同子类对象——这是多态的数组应用
+> - 使用 `instanceof` 判断具体类型后再向下转型,是安全调用特有方法的标准做法
+> - 薪资计算使用 `double` 类型,输出时保留两位小数使用 `System.out.printf("%.2f", value)`

+ 167 - 15
课堂笔记/01-JavaSE基础-笔记/20260724-笔记.md

@@ -56,7 +56,7 @@ animal.eat();   // ✅ 编译看父类有 eat(),运行执行 Dog 的 eat()
 animal.sleep(); // ✅ 编译看父类有 sleep()(抽象),运行执行 Dog 的 sleep()
 // animal.wangWang(); // ❌ 编译报错,父类没有 wangWang()
 ```
-> 📄 来源:`Test01.java`、`Dog.java`
+> 📄 来源:`Test01.java`、`Dog.java`(`course.polymorphism` 包)
 
 ---
 
@@ -88,7 +88,7 @@ public class Mouse implements Usb {
     public void stopUsb()  { System.out.println("USB鼠标关闭"); }
 }
 ```
-> 📄 来源:`Usb.java`、`NoteBook.java`、`Mouse.java`
+> 📄 来源:`Usb.java`、`NoteBook.java`、`Mouse.java`(`course.polymorphism` 包)
 
 ```java
 // 测试多态
@@ -150,7 +150,7 @@ p.sleep();  // ✅ 父类中有 sleep()
 Student s = (Student) p;   // 向下转型
 s.study();  // ✅ 转型后可以调用子类特有方法
 ```
-> 📄 来源:`Demo02.java`
+> 📄 来源:`Demo02.java`(`course.polymorphism` 包)
 
 #### 1.5.3 instanceof 运算符——类型判断
 
@@ -175,7 +175,7 @@ public void 点外卖(外卖类 wm) {
     }
 }
 ```
-> 📄 来源:`Demo02.java`
+> 📄 来源:`Demo02.java`(`course.polymorphism` 包)
 
 ---
 
@@ -208,7 +208,7 @@ public class Test03 {
     }
 }
 ```
-> 📄 来源:`Test03.java`
+> 📄 来源:`Test03.java`(`course.polymorphism` 包)
 
 **执行流程分析**(以传入 `new Student()` 为例):
 ```
@@ -232,7 +232,7 @@ public abstract class Animal {
     public abstract void sleep();    // 抽象方法
 }
 ```
-> 📄 来源:`Animal.java`
+> 📄 来源:`Animal.java`(`course.polymorphism` 包)
 
 ### 2.2 子类继承抽象类
 
@@ -251,7 +251,7 @@ public class Dog extends Animal {
     }
 }
 ```
-> 📄 来源:`Dog.java`
+> 📄 来源:`Dog.java`(`course.polymorphism` 包)
 
 - 子类必须重写父类的所有抽象方法(除非子类也是抽象类)
 - 子类可以重写父类的普通方法(`eat()`)
@@ -284,7 +284,7 @@ public class Teacher extends Person {
     public void play() { System.out.println("教师玩....爽...."); }  // 特有方法
 }
 ```
-> 📄 来源:`Person.java`、`Student.java`、`Teacher.java`
+> 📄 来源:`Person.java`、`Student.java`、`Teacher.java`(`course.polymorphism` 包)
 
 ---
 
@@ -354,34 +354,174 @@ public class Test02 {
     }
 }
 ```
-> 📄 来源:`Test02.java`
+> 📄 来源:`Test02.java(course.polymorphism 包)`
 
 > **关键点**:`NoteBook.useUsb(Usb usb)` 的参数类型是 **接口**,任何实现 `Usb` 接口的类都可以传入,无需修改笔记本的代码即可接入新设备——这就是 **多态提高扩展性** 的典型应用。
 
 ---
 
-## 四、随堂练习要点
+## 四、内部类(Inner Class)
+
+### 4.1 什么是内部类
+
+**概念**:在一个类中定义另一个类。例如,在 `A` 类的内部定义了 `B` 类,`B` 就是内部类。
+
+**使用场景**:当一个类的属性不足以描述内部细节时使用。
+
+```java
+class 人类 {       // 外部类
+    心脏;          // 仅一个属性无法表达心脏的复杂行为
+}
+
+class 汽车 {       // 外部类
+    发动机;        // 发动机应有自己的属性和方法
+}
+```
+
+> 心脏和发动机都依赖于「人类」和「汽车类」而存在,且它们本身也有自己的属性和方法,所以应该设计为 **内部类**。
+
+**定义格式**:
+```java
+class 外部类名 {
+    修饰符 class 内部类名 {
+        // 内部类的成员
+    }
+}
+```
+
+### 4.2 内部类的特点
+
+| 特点 | 说明 |
+|------|------|
+| **① 内部类可直接访问外部类所有成员** | 包括 private 修饰的成员 |
+| **② 外部类访问内部类成员需创建对象** | 外部类方法中 `new` 内部类对象后再调用 |
+
+```java
+public class Person {
+    private String name;
+
+    // 内部类
+    public class Heart {
+        public void jump() {
+            // 内部类直接访问外部类的私有成员
+            System.out.println(name + "的心脏跳动....");
+        }
+    }
+
+    // 外部类方法——必须创建内部类对象才能访问
+    public void method() {
+        Heart h = new Heart();
+        h.jump();
+    }
+}
+```
+> 📄 来源:`Demo01.java`(`course.internalClass` 包)
+
+### 4.3 成员内部类
+
+**成员内部类**:存在于外部类内部,属于外部类的成员,与成员变量、成员方法、代码块在同一层次。
+
+#### 创建格式
+
+```java
+外部类名.内部类名 对象名 = new 外部类().new 内部类();
+// 示例:
+Person.Heart h = new Person().new Heart();
+```
+
+#### 访问权限修饰符
+
+成员内部类可以使用访问权限修饰符(`private`、`public` 等)进行修饰。
+
+```java
+public class Person {
+    // 私有化内部类——外界无法直接访问
+    private class Heart {
+        // ...
+    }
+
+    // 对外提供公共方法获取内部类对象
+    public Heart getHeart() {
+        return new Heart();
+    }
+}
+```
+
+#### 为什么推荐私有化内部类?
+
+```java
+// ❌ 不合理的做法——Heart 和 Person 无关联
+public class Person {
+    Heart heart;
+}
+
+public class Test01 {
+    public static void main(String[] args) {
+        // 可以直接跳过 Person,单独创建 Heart 对象
+        Heart h = new Heart();   // 不符合现实逻辑
+    }
+}
+```
+
+```java
+// ✅ 合理的做法——Heart 作为 Person 的私有内部类
+public class Person {
+    private class Heart {           // 私有内部类
+        public void jump() {
+            System.out.println("心脏跳动...");
+        }
+    }
+    public Heart getHeart() {       // 对外提供方法
+        return new Heart();
+    }
+}
+
+public class Test01 {
+    public static void main(String[] args) {
+        Person person = new Person();
+        // 必须通过 Person 对象才能获取 Heart
+        // person.getHeart();  // 这才是合理的调用链
+    }
+}
+```
+> 📄 来源:`Demo01.java`、`Test01.java`(`course.internalClass` 包)
+
+> **设计原则**:内部类的设计目的就是 **不想让外界直接访问**,仅限外部类自己使用。所以内部类应该私有化,并通过外部类的公共方法对外开放。
+
+### 4.4 内部类与多态的对比
+
+| 对比维度 | 多态 | 内部类 |
+|---------|------|--------|
+| 解决什么问题 | 同一行为在不同子类中有不同实现 | 类的内部细节需要独立描述 |
+| 关系 | 父类/接口 ← 子类/实现类 | 外部类 → 内部类(强依赖) |
+| 访问特点 | 编译看左边,运行看右边 | 内部类可直接访问外部类私有成员 |
+
+## 五、随堂练习要点
 
 | 练习方向 | 涉及知识点 | 对应文件 |
 |---------|-----------|---------|
-| 多态入门 | 多态前提、父类引用指向子类对象、成员访问特点 | `Test01.java`、`Dog.java` |
-| 多态中的转型 | 向上转型、向下转型、instanceof 运算符 | `Demo02.java`、`Test03.java` |
+| 多态入门 | 多态前提、父类引用指向子类对象、成员访问特点 | `Test01.java(course.polymorphism 包)`、`Dog.java(course.polymorphism 包)` |
+| 多态中的转型 | 向上转型、向下转型、instanceof 运算符 | `Demo02.java(course.polymorphism 包)`、`Test03.java(course.polymorphism 包)` |
 | 抽象类多态综合 | 抽象父类 Person、多态参数、向下转型调特有方法 | `Test03.java`、`Person.java` |
-| 接口多态 | Usb 接口、笔记本接入多设备 | `Test02.java`、`NoteBook.java` |
+| 接口多态 | Usb 接口、笔记本接入多设备 | `Test02.java(course.polymorphism 包)`、`NoteBook.java(course.polymorphism 包)` |
+| 内部类入门 | 内部类概念、成员内部类、私有内部类设计 | 包 `course.internalClass` |
 
 ---
 
-## 五、拓展阅读 & 常见面试题
+## 、拓展阅读 & 常见面试题
 
 1. **多态的实现原理**——Java 中多态是通过**动态绑定(后期绑定)**实现的,JVM 在运行时根据对象的实际类型调用对应的方法。
 2. **多态与继承的关系**——多态是基于继承或接口实现的。
 3. **多态的优势**——提高代码的可扩展性和可维护性,符合**开闭原则**(对扩展开放,对修改关闭)。
 4. **向下转型的风险**——向下转型必须配合 `instanceof` 判断,否则可能抛出 `ClassCastException`(类型转换异常)。
 5. **instanceof 的用法**——常用于向下转型前的安全判断,避免强制类型转换异常。
+6. **内部类的使用场景**——当一个类的内部细节(如心脏之于人、发动机之于汽车)需要独立描述时,应设计为内部类。
+7. **内部类的访问规则**——内部类可直接访问外部类的所有成员(含 private);外部类必须创建内部类对象才能访问其成员。
+8. **私有内部类的设计原则**——内部类应私有化,并通过外部类的公共方法对外暴露,确保外部类对内部类的完全控制。
 
 ---
 
-## 六、今日知识图谱
+## 、今日知识图谱
 
 ```
 面向对象三大特征
@@ -401,4 +541,16 @@ public class Test02 {
     │       └── 格式:对象名 instanceof 类型(返回 boolean)
     └── 多态的好处:提高扩展性(开闭原则)
         └── 案例:NoteBook.useUsb(Usb usb)
+
+内部类 ⭐(今日新增)
+├── 概念:类中定义类(心脏之于人、发动机之于汽车)
+├── 特点
+│   ├── 内部类可直接访问外部类所有成员(含 private)
+│   └── 外部类需创建内部类对象才能访问其成员
+├── 成员内部类
+│   ├── 创建格式:外部类名.内部类名 对象名 = new 外部类().new 内部类();
+│   └── 可用访问权限修饰符修饰(private 等)
+└── 私有内部类设计原则
+    ├── 内部类私有化,不被外界直接访问
+    └── 外部类提供公共方法对外暴露内部类功能
 ```