--- title: "04-面向对象三大特征" aliases: - "面向对象三大特征" created: 2025-12-25 --- # 面向对象三大特征 --- ## 〇、三大特征总览 ```drawio ``` --- ## 一、封装(Encapsulation) ### **1.1 概念定义** ```drawio ``` ### **1.2 访问修饰符** | **修饰符** | **同类** | **同包** | **子类** | **不同包** | **使用场景** | | --- | --- | --- | --- | --- | --- | | `private` | ✅ | ❌ | ❌ | ❌ | 属性、内部方法 | | `(default)` | ✅ | ✅ | ❌ | ❌ | 包内工具类 | | `protected` | ✅ | ✅ | ✅ | ❌ | 允许子类访问 | | `public` | ✅ | ✅ | ✅ | ✅ | 对外公开的接口 | **可见性范围图**: ```drawio ``` ### **1.3 完整代码示例** ```java /** * 银行账户类 - 封装示例 */ public class BankAccount { // ========== 私有属性(隐藏数据)========== private String accountNumber; // 账号 private String ownerName; // 户主 private double balance; // 余额 private String password; // 密码 // ========== 构造方法 ========== public BankAccount(String accountNumber, String ownerName, String password) { this.accountNumber = accountNumber; this.ownerName = ownerName; this.password = password; this.balance = 0.0; } // ========== 公开接口(Getter/Setter)========== // 账号:只读(没有 setter) public String getAccountNumber() { // 返回脱敏后的账号 return accountNumber.substring(0, 4) + "****" + accountNumber.substring(accountNumber.length() - 4); } // 户主:只读 public String getOwnerName() { return ownerName; } // 余额:只读(不能直接设置余额) public double getBalance() { return balance; } // 密码:只写(没有 getter,不能读取密码) public void setPassword(String oldPassword, String newPassword) { if (validatePassword(oldPassword)) { this.password = newPassword; System.out.println("密码修改成功"); } else { System.out.println("原密码错误"); } } // ========== 业务方法(公开接口)========== /** * 存款 */ public void deposit(double amount) { if (amount <= 0) { System.out.println("存款金额必须大于0"); return; } balance += amount; System.out.println("存款成功,当前余额:" + balance); } /** * 取款(需要验证密码) */ public boolean withdraw(double amount, String password) { // 1. 验证密码 if (!validatePassword(password)) { System.out.println("密码错误"); return false; } // 2. 验证金额 if (amount <= 0) { System.out.println("取款金额必须大于0"); return false; } // 3. 验证余额 if (amount > balance) { System.out.println("余额不足"); return false; } // 4. 执行取款 balance -= amount; System.out.println("取款成功,当前余额:" + balance); return true; } // ========== 私有方法(隐藏实现)========== /** * 验证密码(私有方法,外部不可见) */ private boolean validatePassword(String inputPassword) { return this.password.equals(inputPassword); } } ``` ### **1.4 使用示例** ```java public class Main { public static void main(String[] args) { BankAccount account = new BankAccount("6222021234567890", "张三", "123456"); // ✅ 通过公开方法操作 account.deposit(1000); // 存款 account.withdraw(500, "123456"); // 取款 // ✅ 通过 getter 获取信息 System.out.println("账号:" + account.getAccountNumber()); // 6222****7890 System.out.println("余额:" + account.getBalance()); // 500.0 // ❌ 无法直接访问私有属性 // account.balance = 999999; // 编译错误 // account.password = "hack"; // 编译错误 // String pwd = account.password; // 编译错误 // ❌ 无法调用私有方法 // account.validatePassword("123456"); // 编译错误 } } ``` ### **1.5 封装的好处** ```drawio ``` ### **1.6 JavaBean 规范** ```java /** * 标准 JavaBean 示例 */ public class User { // 1. 私有属性 private Long id; private String username; private String email; private Integer age; // 2. 无参构造 public User() { } // 3. 全参构造(可选) public User(Long id, String username, String email, Integer age) { this.id = id; this.username = username; this.email = email; this.age = age; } // 4. 标准 Getter/Setter public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getAge() { return age; } public void setAge(Integer age) { // 可以加入验证逻辑 if (age != null && age >= 0 && age <= 150) { this.age = age; } } // 5. toString 方法(可选) @Override public String toString() { return "User{id=" + id + ", username='" + username + "', email='" + email + "', age=" + age + "}"; } } ``` --- ## 二、继承(Inheritance) ### **2.1 概念定义** ```drawio ``` ### **2.2 基本语法** ```java class 子类 extends 父类 { // 子类的属性和方法 } ``` ### **2.3 完整代码示例** #### **父类定义** ```java /** * 员工类(父类) */ public class Employee { // ===== 属性 ===== protected String name; // protected:子类可访问 protected double salary; private String id; // private:子类不可直接访问 // ===== 构造方法 ===== public Employee() { System.out.println("Employee 无参构造"); } public Employee(String name, double salary, String id) { this.name = name; this.salary = salary; this.id = id; System.out.println("Employee 有参构造"); } // ===== 方法 ===== public void work() { System.out.println(name + " 正在工作"); } public void showInfo() { System.out.println("姓名:" + name + ",薪资:" + salary); } // Getter/Setter public String getId() { return id; } public void setId(String id) { this.id = id; } } ``` #### **子类定义** ```java /** * 程序员类(子类) */ public class Programmer extends Employee { // ===== 子类特有属性 ===== private String language; // ===== 构造方法 ===== public Programmer() { super(); // 调用父类无参构造(可省略) System.out.println("Programmer 无参构造"); } public Programmer(String name, double salary, String id, String language) { super(name, salary, id); // 必须在第一行调用父类构造 this.language = language; System.out.println("Programmer 有参构造"); } // ===== 重写父类方法 ===== @Override public void work() { System.out.println(name + " 正在用 " + language + " 编程"); } // ===== 子类特有方法 ===== public void debug() { System.out.println(name + " 正在调试代码"); } public void code() { // 可以访问 protected 属性 System.out.println(name + "(薪资:" + salary + ")开始写代码"); // 不能直接访问 private 属性,需通过 getter System.out.println("工号:" + getId()); } } ``` #### **使用示例** ```java public class Main { public static void main(String[] args) { // 创建子类对象 Programmer p = new Programmer("张三", 15000, "P001", "Java"); // 调用继承的方法 p.showInfo(); // 输出:姓名:张三,薪资:15000.0 // 调用重写的方法 p.work(); // 输出:张三 正在用 Java 编程 // 调用子类特有方法 p.debug(); // 输出:张三 正在调试代码 p.code(); } } ``` **输出结果**: ``` Employee 有参构造 Programmer 有参构造 姓名:张三,薪资:15000.0 张三 正在用 Java 编程 张三 正在调试代码 张三(薪资:15000.0)开始写代码 工号:P001 ``` ### **2.4 super 关键字详解** ```drawio ``` #### **super vs this 对比** | **关键字** | **指向** | **用途** | | --- | --- | --- | | `this` | 当前对象 | 访问本类成员、调用本类构造 | | `super` | 父类部分 | 访问父类成员、调用父类构造 | ```java public class Child extends Parent { private String name = "子类名"; public void show() { System.out.println(this.name); // 子类名 System.out.println(super.name); // 父类名(假设父类有同名属性) } public Child() { // this() 和 super() 不能同时存在,都要求在第一行 super(); // 调用父类构造 // this("参数"); // 编译错误 } } ``` ### **2.5 方法重写(Override)** ```drawio ``` #### **重写 vs 重载 对比** | **对比项** | **重写(Override)** | **重载(Overload)** | | --- | --- | --- | | 发生位置 | 子类与父类之间 | 同一个类中 | | 方法名 | 必须相同 | 必须相同 | | 参数列表 | 必须相同 | 必须不同 | | 返回类型 | 相同或子类型 | 无关 | | 访问修饰符 | 不能更严格 | 无关 | | 目的 | 改变行为 | 提供多种调用方式 | --- ### **2.6 继承的内存结构** ```drawio ``` ### **2.7 继承的要点与限制** ```drawio ``` --- ## 三、多态(Polymorphism) ### **3.1 概念定义** ```drawio ``` ### **3.2 多态的三个必要条件** ```drawio ``` ### **3.3 完整代码示例** #### **定义类结构** ```java /** * 动物类(父类) */ public class Animal { protected String name; public Animal(String name) { this.name = name; } public void makeSound() { System.out.println(name + " 发出声音"); } public void eat() { System.out.println(name + " 正在吃东西"); } } /** * 狗类(子类) */ public class Dog extends Animal { public Dog(String name) { super(name); } @Override public void makeSound() { System.out.println(name + " 汪汪汪!"); } // 子类特有方法 public void guardHouse() { System.out.println(name + " 正在看家"); } } /** * 猫类(子类) */ public class Cat extends Animal { public Cat(String name) { super(name); } @Override public void makeSound() { System.out.println(name + " 喵喵喵~"); } // 子类特有方法 public void catchMouse() { System.out.println(name + " 正在抓老鼠"); } } /** * 鸟类(子类) */ public class Bird extends Animal { public Bird(String name) { super(name); } @Override public void makeSound() { System.out.println(name + " 叽叽喳喳!"); } // 子类特有方法 public void fly() { System.out.println(name + " 正在飞翔"); } } ``` #### **多态使用示例** ```java public class PolymorphismDemo { public static void main(String[] args) { // ========== 向上转型:父类引用指向子类对象 ========== Animal animal1 = new Dog("旺财"); Animal animal2 = new Cat("小花"); Animal animal3 = new Bird("小鸟"); // 同样的方法调用,不同的执行结果 animal1.makeSound(); // 旺财 汪汪汪! animal2.makeSound(); // 小花 喵喵喵~ animal3.makeSound(); // 小鸟 叽叽喳喳! // ========== 多态数组 ========== Animal[] animals = { new Dog("大黄"), new Cat("咪咪"), new Bird("鹦鹉") }; // 统一处理 for (Animal animal : animals) { animal.makeSound(); // 自动调用各自的实现 } // ========== 多态参数 ========== feedAnimal(new Dog("小白")); feedAnimal(new Cat("小黑")); } // 多态作为方法参数 public static void feedAnimal(Animal animal) { animal.eat(); // 所有动物都能吃 animal.makeSound(); // 各自发出不同的声音 } } ``` ### **3.4 多态的执行原理** ```drawio ``` ### **3.5 向上转型与向下转型** ```drawio ``` #### **代码示例** ```java public class CastDemo { public static void main(String[] args) { // ===== 向上转型 ===== Animal animal = new Dog("旺财"); // 自动向上转型 animal.makeSound(); // ✅ 可以调用 animal.eat(); // ✅ 可以调用 // animal.guardHouse(); // ❌ 编译错误!父类引用看不到子类特有方法 // ===== 向下转型 ===== if (animal instanceof Dog) { // 先判断类型 Dog dog = (Dog) animal; // 强制向下转型 dog.guardHouse(); // ✅ 现在可以调用子类方法 } // ===== 错误的向下转型 ===== Animal animal2 = new Cat("小花"); // Dog dog2 = (Dog) animal2; // ❌ 运行时异常:ClassCastException // ===== 安全的向下转型 ===== if (animal2 instanceof Dog) { Dog dog2 = (Dog) animal2; dog2.guardHouse(); } else { System.out.println("animal2 不是 Dog 类型"); } // ===== Java 16+ 新语法:模式匹配 ===== if (animal instanceof Dog dog) { // 判断 + 转换一步完成 dog.guardHouse(); } } } ``` ### **3.6 instanceof 关键字** ```drawio ``` ### **3.7 多态的实际应用** #### **应用1:统一处理不同类型** ```java public class Zoo { private List animals = new ArrayList<>(); public void addAnimal(Animal animal) { animals.add(animal); // 可以添加任何 Animal 的子类 } // 统一喂食 public void feedAll() { for (Animal animal : animals) { animal.eat(); // 多态调用 } } // 统一演出 public void performAll() { for (Animal animal : animals) { animal.makeSound(); // 多态调用 } } } // 使用 Zoo zoo = new Zoo(); zoo.addAnimal(new Dog("旺财")); zoo.addAnimal(new Cat("咪咪")); zoo.addAnimal(new Bird("鹦鹉")); zoo.performAll(); // 每个动物发出自己的声音 ``` #### **应用2:策略模式** ```java // 支付策略接口 interface PaymentStrategy { void pay(double amount); } // 具体策略 class WeChatPay implements PaymentStrategy { @Override public void pay(double amount) { System.out.println("微信支付:" + amount + " 元"); } } class AliPay implements PaymentStrategy { @Override public void pay(double amount) { System.out.println("支付宝支付:" + amount + " 元"); } } class CreditCardPay implements PaymentStrategy { @Override public void pay(double amount) { System.out.println("信用卡支付:" + amount + " 元"); } } // 购物车(使用多态) class ShoppingCart { private PaymentStrategy paymentStrategy; public void setPaymentStrategy(PaymentStrategy strategy) { this.paymentStrategy = strategy; // 可以接收任何支付策略 } public void checkout(double amount) { paymentStrategy.pay(amount); // 多态调用 } } // 使用 ShoppingCart cart = new ShoppingCart(); cart.setPaymentStrategy(new WeChatPay()); cart.checkout(100); // 微信支付:100 元 cart.setPaymentStrategy(new AliPay()); cart.checkout(200); // 支付宝支付:200 元 ``` ### **3.8 多态的优缺点** ```drawio ``` --- ## 四、三大特征综合对比与总结 ### **4.1 对比表** | **特征** | **核心思想** | **关键字/机制** | **主要作用** | | --- | --- | --- | --- | | **封装** | 隐藏细节 | private/getter/setter | 保护数据安全 | | **继承** | 代码复用 | extends/super | 建立类层次结构 | | **多态** | 统一接口 | 重写/向上转型 | 灵活扩展 | --- ### **4.2 三者关系图** ```drawio ``` ### **4.3 综合代码示例** ```java /** * 综合示例:图形绘制系统 */ // ========== 封装:隐藏属性,提供接口 ========== abstract class Shape { private String color; // 封装:私有属性 private boolean filled; public Shape(String color, boolean filled) { this.color = color; this.filled = filled; } // 封装:公开接口 public String getColor() { return color; } public void setColor(String color) { this.color = color; } public boolean isFilled() { return filled; } // 抽象方法 public abstract double getArea(); public abstract double getPerimeter(); @Override public String toString() { return "Shape[color=" + color + ", filled=" + filled + "]"; } } // ========== 继承:复用父类代码 ========== class Circle extends Shape { private double radius; public Circle(String color, boolean filled, double radius) { super(color, filled); // 调用父类构造 this.radius = radius; } // 重写抽象方法 @Override public double getArea() { return Math.PI * radius * radius; } @Override public double getPerimeter() { return 2 * Math.PI * radius; } } class Rectangle extends Shape { private double width; private double height; public Rectangle(String color, boolean filled, double width, double height) { super(color, filled); this.width = width; this.height = height; } @Override public double getArea() { return width * height; } @Override public double getPerimeter() { return 2 * (width + height); } } // ========== 多态:统一处理不同图形 ========== class Canvas { private List shapes = new ArrayList<>(); // 多态参数 public void addShape(Shape shape) { shapes.add(shape); } // 多态调用 public double getTotalArea() { double total = 0; for (Shape shape : shapes) { total += shape.getArea(); // 调用各自的实现 } return total; } public void printAllShapes() { for (Shape shape : shapes) { System.out.println(shape + ", Area=" + shape.getArea()); } } } // ========== 使用 ========== public class Main { public static void main(String[] args) { Canvas canvas = new Canvas(); // 多态:父类引用指向子类对象 canvas.addShape(new Circle("红色", true, 5)); canvas.addShape(new Rectangle("蓝色", false, 3, 4)); canvas.addShape(new Circle("绿色", true, 3)); canvas.printAllShapes(); System.out.println("总面积:" + canvas.getTotalArea()); } } ``` ### **4.4 速查表** | **特征** | **核心要点** | **实现方式** | | --- | --- | --- | | **封装** | 隐藏数据,暴露接口 | private + getter/setter | | **继承** | 子类复用父类 | extends + super | | **多态** | 同一行为多种形态 | 继承 + 重写 + 向上转型 | --- ### **4.5 记忆口诀** ``` ┌─────────────────────────────────────────────────────────────────┐ │ 记忆口诀 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 封装:藏好属性露接口,getter/setter 来帮忙 │ │ │ │ 继承:extends 连接父与子,super 调用不能忘 │ │ │ │ 多态:父类引用指向子,编译看左运行右 │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ 多态三要素: │ │ ① 有继承 ② 有重写 ③ 父类引用指向子类对象 │ │ │ │ 方法重写规则(两同两小一大): │ │ • 两同:方法名、参数列表相同 │ │ • 两小:返回类型 ≤ 父类、异常 ≤ 父类 │ │ • 一大:访问权限 ≥ 父类 │ │ │ └─────────────────────────────────────────────────────────────────┘ ```