--- title: "06-面向对象编程(OOP)" created: 2025-11-27 tags: - Java --- # 面向对象编程(OOP) **封装、继承和多态:Java 的三大面向对象编程(OOP)特性** Java 是一种面向对象编程语言(区别于[[05-面向对象or面向过程|面向对象or面向过程]]),面向对象编程(OOP)通过将数据和方法封装在对象中,旨在提高程序的可维护性、可扩展性和复用性。OOP 主要包括以下三大核心特性:**封装**、**继承**、**多态**。 ## **一、封装(Encapsulation)** ### **1.1 封装的核心概念** ```java /** * 封装:将数据和操作数据的方法绑定在一起,隐藏内部实现细节 * 核心原则:高内聚、低耦合 */ public class BankAccount { // ========== 1. 数据隐藏(私有字段) ========== private String accountNumber; private String ownerName; private double balance; private List transactions; // ========== 2. 构造器(初始化对象) ========== public BankAccount(String accountNumber, String ownerName) { this.accountNumber = accountNumber; this.ownerName = ownerName; this.balance = 0.0; this.transactions = new ArrayList<>(); } // ========== 3. 公共接口(受控访问) ========== // Getter:只读访问 public String getAccountNumber() { return accountNumber; } public String getOwnerName() { return ownerName; } // 只提供余额查询,不提供直接修改 public double getBalance() { return balance; } // Setter:带验证的写入 public void setOwnerName(String ownerName) { if (ownerName == null || ownerName.trim().isEmpty()) { throw new IllegalArgumentException("Owner name cannot be empty"); } this.ownerName = ownerName; } // ========== 4. 业务方法(封装业务逻辑) ========== /** * 存款 * ✅ 优点: * - 参数验证 * - 业务规则集中管理 * - 记录交易历史 */ public void deposit(double amount) { if (amount <= 0) { throw new IllegalArgumentException("Deposit amount must be positive"); } balance += amount; transactions.add(new Transaction("DEPOSIT", amount, balance)); logTransaction("Deposited: " + amount); } /** * 取款 * ✅ 封装了复杂的业务逻辑 */ public boolean withdraw(double amount) { // 验证 1:金额有效性 if (amount <= 0) { throw new IllegalArgumentException("Withdrawal amount must be positive"); } // 验证 2:余额充足性 if (amount > balance) { System.out.println("Insufficient balance"); return false; } // 验证 3:单次取款限额 if (amount > 10000) { System.out.println("Single withdrawal limit exceeded"); return false; } balance -= amount; transactions.add(new Transaction("WITHDRAW", amount, balance)); logTransaction("Withdrew: " + amount); return true; } /** * 转账 * ✅ 封装了跨账户操作的复杂性 */ public boolean transfer(BankAccount target, double amount) { if (target == null) { throw new IllegalArgumentException("Target account cannot be null"); } if (this.withdraw(amount)) { target.deposit(amount); logTransaction("Transferred " + amount + " to " + target.getAccountNumber()); return true; } return false; } // ========== 5. 内部辅助方法(私有) ========== private void logTransaction(String message) { System.out.println("[" + LocalDateTime.now() + "] " + message); } // ========== 6. 不可变视图(防御性拷贝) ========== public List getTransactions() { // ❌ 错误:直接返回内部集合 // return transactions; // ✅ 正确:返回不可变副本 return Collections.unmodifiableList(new ArrayList<>(transactions)); } /** * 交易记录(不可变类) */ public static class Transaction { private final String type; private final double amount; private final double balanceAfter; private final LocalDateTime timestamp; public Transaction(String type, double amount, double balanceAfter) { this.type = type; this.amount = amount; this.balanceAfter = balanceAfter; this.timestamp = LocalDateTime.now(); } // 只提供 getter,无 setter(不可变) public String getType() { return type; } public double getAmount() { return amount; } public double getBalanceAfter() { return balanceAfter; } public LocalDateTime getTimestamp() { return timestamp; } } } ``` ### **1.2 访问控制修饰符** ```java /** * Java 四种访问级别 */ public class AccessControlDemo { // ========== 1. private(类内部) ========== private String privateField = "private"; private void privateMethod() { System.out.println("Only accessible within this class"); } // ========== 2. default(包级别) ========== String defaultField = "default"; // 无修饰符 void defaultMethod() { System.out.println("Accessible within the same package"); } // ========== 3. protected(包 + 子类) ========== protected String protectedField = "protected"; protected void protectedMethod() { System.out.println("Accessible within package and subclasses"); } // ========== 4. public(所有地方) ========== public String publicField = "public"; public void publicMethod() { System.out.println("Accessible everywhere"); } /** * 访问级别表格: * * ┌──────────┬────────┬──────┬────────┬──────────┐ * │ 修饰符 │ 同类 │ 同包 │ 子类 │ 其他包 │ * ├──────────┼────────┼──────┼────────┼──────────┤ * │ private │ ✅ │ ❌ │ ❌ │ ❌ │ * │ default │ ✅ │ ✅ │ ❌ │ ❌ │ * │protected │ ✅ │ ✅ │ ✅ │ ❌ │ * │ public │ ✅ │ ✅ │ ✅ │ ✅ │ * └──────────┴────────┴──────┴────────┴──────────┘ */ } // ========== 同包类测试 ========== class SamePackageTest { public void test() { AccessControlDemo demo = new AccessControlDemo(); // demo.privateField; // ❌ 编译错误 // demo.privateMethod(); // ❌ 编译错误 String s1 = demo.defaultField; // ✅ demo.defaultMethod(); // ✅ String s2 = demo.protectedField; // ✅ demo.protectedMethod(); // ✅ String s3 = demo.publicField; // ✅ demo.publicMethod(); // ✅ } } // ========== 不同包子类测试 ========== package com.other; class SubclassTest extends AccessControlDemo { public void test() { // privateField; // ❌ 编译错误 // defaultField; // ❌ 编译错误(不同包) String s1 = protectedField; // ✅ protectedMethod(); // ✅ String s2 = publicField; // ✅ publicMethod(); // ✅ } } ``` ### **1.3 封装的最佳实践** ```java /** * 封装的设计原则 */ public class EncapsulationBestPractices { // ========== 1. 最小化可变性 ========== // ❌ 错误:可变字段 public List items = new ArrayList<>(); // ✅ 正确:不可变字段 private final List items2 = new ArrayList<>(); public List getItems() { return Collections.unmodifiableList(items2); } public void addItem(String item) { items2.add(item); } // ========== 2. 防御性拷贝 ========== private Date birthDate; // ❌ 错误:返回内部可变对象的引用 public Date getBirthDate() { return birthDate; } // ✅ 正确:返回副本 public Date getBirthDateSafe() { return birthDate == null ? null : new Date(birthDate.getTime()); } // ✅ 更好:使用不可变类型 private final LocalDate birthDate2 = LocalDate.now(); public LocalDate getBirthDate2() { return birthDate2; // LocalDate 不可变,安全返回 } // ========== 3. JavaBeans 规范 ========== private String name; // 标准 getter/setter 命名 public String getName() { return name; } public void setName(String name) { this.name = name; } // boolean 类型特殊命名 private boolean active; public boolean isActive() { // 使用 is 前缀 return active; } public void setActive(boolean active) { this.active = active; } // ========== 4. Lombok 简化(可选) ========== /** * 使用 Lombok 注解自动生成代码 */ @Data // 生成 getter/setter/toString/equals/hashCode @Builder // 生成建造者模式 @AllArgsConstructor @NoArgsConstructor public static class User { private Long id; private String username; private String email; @Setter(AccessLevel.NONE) // 不生成 setter private LocalDateTime createdAt; } // 使用示例 User user = User.builder() .id(1L) .username("admin") .email("admin@example.com") .build(); } ``` ## **二、继承(Inheritance)** ### **2.1 继承的基础** ```java /** * 继承:子类继承父类的属性和方法 * 关键词:extends */ // ========== 父类(基类、超类) ========== public class Animal { // 父类字段 protected String name; protected int age; private String species; // private 字段子类不可直接访问 // 父类构造器 public Animal(String name, int age, String species) { this.name = name; this.age = age; this.species = species; } // 父类方法 public void eat() { System.out.println(name + " is eating"); } public void sleep() { System.out.println(name + " is sleeping"); } // final 方法:子类不能重写 public final void breathe() { System.out.println(name + " is breathing"); } // protected 方法:子类可访问 protected void makeSound() { System.out.println("Some generic sound"); } // Getter public String getSpecies() { return species; } } // ========== 子类(派生类) ========== public class Dog extends Animal { // 子类独有字段 private String breed; // 子类构造器:必须调用父类构造器 public Dog(String name, int age, String breed) { super(name, age, "Canine"); // ✅ super() 调用父类构造器 this.breed = breed; } // ========== 方法重写(Override) ========== /** * @Override 注解: * - 编译期检查是否正确重写 * - 提高代码可读性 */ @Override public void eat() { System.out.println(name + " is eating dog food"); } @Override protected void makeSound() { System.out.println(name + " barks: Woof! Woof!"); } // ❌ 编译错误:不能重写 final 方法 // @Override // public void breathe() {} // ========== 子类独有方法 ========== public void fetch() { System.out.println(name + " is fetching the ball"); } public void wagTail() { System.out.println(name + " is wagging tail"); } // ========== 访问父类成员 ========== public void showInfo() { // 访问 protected 字段 System.out.println("Name: " + name); // ✅ System.out.println("Age: " + age); // ✅ // 访问 private 字段:需要通过 getter System.out.println("Species: " + getSpecies()); // ✅ // 调用父类方法 super.eat(); // 显式调用父类版本 this.eat(); // 调用子类重写版本 } } // ========== 使用示例 ========== public class InheritanceDemo { public static void main(String[] args) { Dog dog = new Dog("Buddy", 3, "Golden Retriever"); // 调用继承的方法 dog.sleep(); // 来自 Animal dog.breathe(); // 来自 Animal(final) // 调用重写的方法 dog.eat(); // 来自 Dog(重写) dog.makeSound(); // 来自 Dog(重写) // 调用子类独有方法 dog.fetch(); // 来自 Dog dog.wagTail(); // 来自 Dog dog.showInfo(); } } ``` ### **2.2 super 关键字详解** ```java /** * super 关键字的三种用法 */ public class SuperKeywordDemo { // ========== 父类 ========== static class Parent { protected String name = "Parent"; public Parent() { System.out.println("Parent constructor"); } public Parent(String name) { this.name = name; System.out.println("Parent constructor with name: " + name); } public void display() { System.out.println("Parent display"); } public void print() { System.out.println("Parent print"); } } // ========== 子类 ========== static class Child extends Parent { private String name = "Child"; public Child() { // super() 必须是构造器的第一条语句 super("ParentName"); // ✅ 用法 1:调用父类构造器 System.out.println("Child constructor"); } @Override public void display() { // ✅ 用法 2:访问父类字段 System.out.println("Parent name: " + super.name); System.out.println("Child name: " + this.name); } @Override public void print() { // ✅ 用法 3:调用父类方法 super.print(); // 调用父类版本 System.out.println("Child print"); } public void showAll() { super.display(); // 调用父类 display() this.display(); // 调用子类 display() } } public static void main(String[] args) { Child child = new Child(); /** * 输出: * Parent constructor with name: ParentName * Child constructor */ child.display(); /** * 输出: * Parent name: Parent * Child name: Child */ child.print(); /** * 输出: * Parent print * Child print */ } /** * super vs this: * * super: * - 访问父类成员 * - 调用父类构造器 * - 必须是构造器第一条语句 * * this: * - 访问当前类成员 * - 调用当前类其他构造器 * - 必须是构造器第一条语句 * * ⚠️ super() 和 this() 不能同时出现! */ } ``` ### **2.3 构造器链** ```java /** * 构造器链:子类构造器自动调用父类构造器 */ public class ConstructorChainDemo { // ========== 三层继承关系 ========== static class GrandParent { public GrandParent() { System.out.println("1. GrandParent()"); } } static class Parent extends GrandParent { public Parent() { super(); // 隐式调用(可省略) System.out.println("2. Parent()"); } } static class Child extends Parent { public Child() { super(); // 隐式调用(可省略) System.out.println("3. Child()"); } } public static void main(String[] args) { new Child(); /** * 输出: * 1. GrandParent() * 2. Parent() * 3. Child() * * 执行顺序:从顶层到底层 */ } // ========== 构造器重载 + 链式调用 ========== static class Person { private String name; private int age; private String address; // 主构造器 public Person(String name, int age, String address) { this.name = name; this.age = age; this.address = address; System.out.println("Full constructor"); } // 委托构造器 public Person(String name, int age) { this(name, age, "Unknown"); // 调用主构造器 System.out.println("Two-arg constructor"); } public Person(String name) { this(name, 0); // 调用两参数构造器 System.out.println("One-arg constructor"); } public Person() { this("Unknown"); // 调用单参数构造器 System.out.println("No-arg constructor"); } } static class Employee extends Person { private String company; public Employee(String name, int age, String address, String company) { super(name, age, address); // 必须先调用父类构造器 this.company = company; System.out.println("Employee constructor"); } } public static void test() { new Employee("Alice", 30, "NYC", "Google"); /** * 输出: * Full constructor * Employee constructor */ } /** * 构造器调用规则: * * 1️⃣ 如果子类构造器没有显式调用 super(),编译器自动插入 super() * 2️⃣ 如果父类没有无参构造器,子类必须显式调用父类有参构造器 * 3️⃣ super() 或 this() 必须是构造器的第一条语句 * 4️⃣ super() 和 this() 不能同时出现 */ } ``` ### **2.4 继承与初始化顺序** ```java /** * 完整的初始化顺序 */ public class InitializationOrderDemo { static class Parent { // 1. 父类静态字段 private static String staticField = initStaticField(); // 2. 父类静态块 static { System.out.println("2. Parent static block"); } // 3. 父类实例字段 private String instanceField = initInstanceField(); // 4. 父类实例块 { System.out.println("4. Parent instance block"); } // 5. 父类构造器 public Parent() { System.out.println("5. Parent constructor"); } private static String initStaticField() { System.out.println("1. Parent static field"); return "parent static"; } private String initInstanceField() { System.out.println("3. Parent instance field"); return "parent instance"; } } static class Child extends Parent { // 6. 子类静态字段 private static String staticField = initStaticField(); // 7. 子类静态块 static { System.out.println("7. Child static block"); } // 8. 子类实例字段 private String instanceField = initInstanceField(); // 9. 子类实例块 { System.out.println("9. Child instance block"); } // 10. 子类构造器 public Child() { super(); System.out.println("10. Child constructor"); } private static String initStaticField() { System.out.println("6. Child static field"); return "child static"; } private String initInstanceField() { System.out.println("8. Child instance field"); return "child instance"; } } public static void main(String[] args) { System.out.println("=== First instantiation ==="); new Child(); System.out.println("\n=== Second instantiation ==="); new Child(); /** * 输出: * === First instantiation === * 1. Parent static field * 2. Parent static block * 6. Child static field * 7. Child static block * 3. Parent instance field * 4. Parent instance block * 5. Parent constructor * 8. Child instance field * 9. Child instance block * 10. Child constructor * * === Second instantiation === * 3. Parent instance field * 4. Parent instance block * 5. Parent constructor * 8. Child instance field * 9. Child instance block * 10. Child constructor * * ⚠️ 静态内容只初始化一次! */ } /** * 初始化顺序总结: * * 1️⃣ 父类静态成员(字段 + 块) * 2️⃣ 子类静态成员(字段 + 块) * 3️⃣ 父类实例成员(字段 + 块) * 4️⃣ 父类构造器 * 5️⃣ 子类实例成员(字段 + 块) * 6️⃣ 子类构造器 */ } ``` ### **2.5 方法重写(Override)详解** ```java /** * 方法重写的规则和最佳实践 */ public class OverrideDemo { static class Parent { // 返回类型:Object public Object getValue() { return "Parent"; } // 访问修饰符:protected protected void display() { System.out.println("Parent display"); } // 抛出异常:IOException public void process() throws IOException { System.out.println("Parent process"); } // final 方法:不能重写 public final void finalMethod() { System.out.println("Final method"); } // static 方法:不能重写(可以隐藏) public static void staticMethod() { System.out.println("Parent static"); } } static class Child extends Parent { // ========== 规则 1:协变返回类型 ========== @Override public String getValue() { // String 是 Object 的子类 ✅ return "Child"; } // ========== 规则 2:访问权限不能更严格 ========== @Override public void display() { // protected -> public ✅ System.out.println("Child display"); } // ❌ 编译错误:不能从 protected 降为 private // @Override // private void display() {} // ========== 规则 3:异常限制 ========== @Override public void process() throws FileNotFoundException { // IOException 的子类 ✅ System.out.println("Child process"); } // ❌ 编译错误:不能抛出更宽泛的异常 // @Override // public void process() throws Exception {} // ========== 规则 4:不能重写 final 方法 ========== // ❌ 编译错误 // @Override // public void finalMethod() {} // ========== 规则 5:static 方法不是重写,是隐藏 ========== public static void staticMethod() { // 不是 @Override System.out.println("Child static"); } } public static void main(String[] args) { // ========== 多态调用 ========== Parent p = new Child(); Object obj = p.getValue(); // 运行时调用 Child.getValue() System.out.println(obj); // 输出:Child p.display(); // 运行时调用 Child.display() // ========== 静态方法调用(编译时绑定) ========== p.staticMethod(); // 输出:Parent static(不是多态!) Child.staticMethod(); // 输出:Child static /** * 重写 vs 隐藏: * * 重写(Override): * - 实例方法 * - 运行时多态(动态绑定) * - 使用 @Override 注解 * * 隐藏(Hiding): * - 静态方法、静态字段 * - 编译时绑定 * - 无 @Override 注解 */ } } ``` ## **三、多态(Polymorphism)** ### **3.1 多态的基本概念** ```java /** * 多态:同一个引用类型,指向不同的对象时,调用同一个方法表现出不同的行为 * * 多态的三个必要条件: * 1️⃣ 继承(或实现接口) * 2️⃣ 重写(子类重写父类方法) * 3️⃣ 向上转型(父类引用指向子类对象) */ public class PolymorphismBasics { // ========== 父类 ========== static class Animal { public void makeSound() { System.out.println("Some generic sound"); } public void eat() { System.out.println("Animal is eating"); } } // ========== 子类 1 ========== static class Dog extends Animal { @Override public void makeSound() { System.out.println("Woof! Woof!"); } @Override public void eat() { System.out.println("Dog is eating bones"); } // 子类独有方法 public void fetch() { System.out.println("Dog is fetching"); } } // ========== 子类 2 ========== static class Cat extends Animal { @Override public void makeSound() { System.out.println("Meow! Meow!"); } @Override public void eat() { System.out.println("Cat is eating fish"); } // 子类独有方法 public void climb() { System.out.println("Cat is climbing"); } } // ========== 子类 3 ========== static class Bird extends Animal { @Override public void makeSound() { System.out.println("Chirp! Chirp!"); } @Override public void eat() { System.out.println("Bird is eating seeds"); } // 子类独有方法 public void fly() { System.out.println("Bird is flying"); } } // ========== 多态演示 ========== public static void main(String[] args) { // ========== 1. 向上转型(Upcasting) ========== Animal animal1 = new Dog(); // ✅ 自动转型 Animal animal2 = new Cat(); // ✅ 自动转型 Animal animal3 = new Bird(); // ✅ 自动转型 // 多态调用:运行时根据实际对象类型调用对应方法 animal1.makeSound(); // 输出:Woof! Woof! animal2.makeSound(); // 输出:Meow! Meow! animal3.makeSound(); // 输出:Chirp! Chirp! animal1.eat(); // 输出:Dog is eating bones animal2.eat(); // 输出:Cat is eating fish animal3.eat(); // 输出:Bird is eating seeds // ❌ 不能调用子类独有方法 // animal1.fetch(); // 编译错误 // animal2.climb(); // 编译错误 // animal3.fly(); // 编译错误 // ========== 2. 向下转型(Downcasting) ========== // ✅ 正确的向下转型 if (animal1 instanceof Dog) { Dog dog = (Dog) animal1; dog.fetch(); // 现在可以调用子类方法 } // ❌ 错误的向下转型:运行时异常 try { Dog dog = (Dog) animal2; // animal2 实际是 Cat dog.fetch(); } catch (ClassCastException e) { System.out.println("ClassCastException: Cannot cast Cat to Dog"); } // ========== 3. 数组多态 ========== Animal[] animals = { new Dog(), new Cat(), new Bird(), new Dog(), new Cat() }; // 统一处理不同类型的对象 for (Animal animal : animals) { animal.makeSound(); // 多态调用 animal.eat(); System.out.println("---"); } // ========== 4. 集合多态 ========== List animalList = new ArrayList<>(); animalList.add(new Dog()); animalList.add(new Cat()); animalList.add(new Bird()); for (Animal animal : animalList) { animal.makeSound(); } // ========== 5. 方法参数多态 ========== feedAnimal(new Dog()); feedAnimal(new Cat()); feedAnimal(new Bird()); } /** 方法参数多态:接受父类类型参数,可以传入任意子类对象 */ public static void feedAnimal(Animal animal) { System.out.println("Feeding the animal..."); animal.eat(); // 多态调用 } } ``` ### **3.2 编译时多态(方法重载)** ```java /** * 编译时多态(静态多态):方法重载(Overloading) * 特点:编译期确定调用哪个方法 */ public class CompileTimePolymorphism { // ========== 方法重载的四种方式 ========== // 1️⃣ 参数个数不同 public void print(String message) { System.out.println("String: " + message); } public void print(String message, int count) { for (int i = 0; i < count; i++) { System.out.println(message); } } // 2️⃣ 参数类型不同 public void display(int value) { System.out.println("int: " + value); } public void display(double value) { System.out.println("double: " + value); } public void display(String value) { System.out.println("String: " + value); } // 3️⃣ 参数顺序不同 public void process(String name, int age) { System.out.println(name + " is " + age + " years old"); } public void process(int age, String name) { System.out.println(name + " is " + age + " years old"); } // 4️⃣ 可变参数重载 public void sum(int... numbers) { int total = 0; for (int num : numbers) { total += num; } System.out.println("Sum: " + total); } public void sum(int a, int b) { System.out.println("Sum of two: " + (a + b)); } // ========== 重载解析优先级 ========== public static void main(String[] args) { CompileTimePolymorphism demo = new CompileTimePolymorphism(); // 测试 1:精确匹配 demo.display(10); // 调用 display(int) demo.display(10.5); // 调用 display(double) demo.display("Hello"); // 调用 display(String) // 测试 2:自动类型提升 byte b = 5; demo.display(b); // byte -> int,调用 display(int) short s = 10; demo.display(s); // short -> int,调用 display(int) float f = 3.14f; demo.display(f); // float -> double,调用 display(double) // 测试 3:装箱 Integer integer = 100; demo.display(integer); // Integer -> int(自动拆箱),调用 display(int) // 测试 4:可变参数 demo.sum(1, 2); // 优先调用 sum(int, int) demo.sum(1, 2, 3); // 调用 sum(int...) demo.sum(); // 调用 sum(int...) } /** * 重载解析优先级(从高到低): * * 1️⃣ 精确匹配 * 2️⃣ 自动类型提升(byte->short->int->long->float->double) * 3️⃣ 自动装箱/拆箱 * 4️⃣ 可变参数 */ // ========== 不能重载的情况 ========== // ❌ 返回类型不同不构成重载 // public int getValue() { return 1; } // public double getValue() { return 1.0; } // 编译错误 // ❌ 仅访问修饰符不同不构成重载 // public void method() {} // private void method() {} // 编译错误 // ❌ 仅抛出异常不同不构成重载 // public void doSomething() {} // public void doSomething() throws Exception {} // 编译错误 } ``` ### **3.3 运行时多态(方法重写)** ```java /** * 运行时多态(动态多态):方法重写(Overriding) * 特点:运行时根据实际对象类型确定调用哪个方法 */ public class RuntimePolymorphism { // ========== 父类 ========== static class Shape { protected String color; public Shape(String color) { this.color = color; } // 可重写方法 public double getArea() { return 0; } public void draw() { System.out.println("Drawing a shape"); } public void displayInfo() { System.out.println("Color: " + color + ", Area: " + getArea()); } } // ========== 子类 1:Circle ========== static class Circle extends Shape { private double radius; public Circle(String color, double radius) { super(color); this.radius = radius; } @Override public double getArea() { return Math.PI * radius * radius; } @Override public void draw() { System.out.println("Drawing a circle with radius " + radius); } } // ========== 子类 2:Rectangle ========== static class Rectangle extends Shape { private double width; private double height; public Rectangle(String color, double width, double height) { super(color); this.width = width; this.height = height; } @Override public double getArea() { return width * height; } @Override public void draw() { System.out.println("Drawing a rectangle " + width + "x" + height); } } // ========== 子类 3:Triangle ========== static class Triangle extends Shape { private double base; private double height; public Triangle(String color, double base, double height) { super(color); this.base = base; this.height = height; } @Override public double getArea() { return 0.5 * base * height; } @Override public void draw() { System.out.println("Drawing a triangle"); } } // ========== 运行时多态演示 ========== public static void main(String[] args) { // ========== 1. 基本多态调用 ========== Shape shape1 = new Circle("Red", 5.0); Shape shape2 = new Rectangle("Blue", 4.0, 6.0); Shape shape3 = new Triangle("Green", 3.0, 4.0); // 运行时确定调用哪个 getArea() System.out.println("Circle area: " + shape1.getArea()); System.out.println("Rectangle area: " + shape2.getArea()); System.out.println("Triangle area: " + shape3.getArea()); // ========== 2. 方法链中的多态 ========== shape1.displayInfo(); // displayInfo() 中调用 getArea(),多态! shape2.displayInfo(); shape3.displayInfo(); /** * displayInfo() 在父类中定义,但调用的 getArea() * 是运行时根据实际对象类型确定的! */ // ========== 3. 集合中的多态 ========== List shapes = Arrays.asList( new Circle("Red", 5.0), new Rectangle("Blue", 4.0, 6.0), new Triangle("Green", 3.0, 4.0), new Circle("Yellow", 3.0) ); // 统一处理不同形状 double totalArea = 0; for (Shape shape : shapes) { shape.draw(); // 多态调用 totalArea += shape.getArea(); // 多态调用 } System.out.println("Total area: " + totalArea); // ========== 4. instanceof 类型检查 ========== for (Shape shape : shapes) { if (shape instanceof Circle) { System.out.println("Found a circle"); } else if (shape instanceof Rectangle) { System.out.println("Found a rectangle"); } else if (shape instanceof Triangle) { System.out.println("Found a triangle"); } } // ========== 5. 模式匹配(JDK 16+) ========== for (Shape shape : shapes) { if (shape instanceof Circle circle) { // 模式匹配 + 自动转型 System.out.println("Circle radius: " + circle.radius); } else if (shape instanceof Rectangle rect) { System.out.println("Rectangle: " + rect.width + "x" + rect.height); } } } /** * 多态的底层实现:虚方法表(Virtual Method Table, VMT) * * 每个类都有一个虚方法表,存储该类的所有虚方法的地址。 * * Shape VMT: * ┌─────────────┬──────────────┐ * │ getArea() │ Shape.getArea│ * │ draw() │ Shape.draw │ * └─────────────┴──────────────┘ * * Circle VMT: * ┌─────────────┬──────────────┐ * │ getArea() │ Circle.getArea│ ⬅️ 重写 * │ draw() │ Circle.draw │ ⬅️ 重写 * └─────────────┴──────────────┘ * * 调用流程: * 1. 根据对象找到其类的虚方法表 * 2. 在虚方法表中查找方法地址 * 3. 调用对应地址的方法 */ } ``` ### **3.4 多态的实际应用** ```java /** * 多态的实际应用场景 */ public class PolymorphismApplications { // ========== 场景 1:支付系统 ========== interface PaymentMethod { boolean pay(double amount); String getPaymentType(); } static class CreditCardPayment implements PaymentMethod { private String cardNumber; public CreditCardPayment(String cardNumber) { this.cardNumber = cardNumber; } @Override public boolean pay(double amount) { System.out.println("Paying $" + amount + " with Credit Card " + cardNumber); return true; } @Override public String getPaymentType() { return "Credit Card"; } } static class PayPalPayment implements PaymentMethod { private String email; public PayPalPayment(String email) { this.email = email; } @Override public boolean pay(double amount) { System.out.println("Paying $" + amount + " with PayPal " + email); return true; } @Override public String getPaymentType() { return "PayPal"; } } static class WeChatPayment implements PaymentMethod { private String phoneNumber; public WeChatPayment(String phoneNumber) { this.phoneNumber = phoneNumber; } @Override public boolean pay(double amount) { System.out.println("Paying $" + amount + " with WeChat " + phoneNumber); return true; } @Override public String getPaymentType() { return "WeChat Pay"; } } /** * 订单类:使用多态处理不同支付方式 */ static class Order { private double totalAmount; private PaymentMethod paymentMethod; // 多态字段 public Order(double totalAmount) { this.totalAmount = totalAmount; } public void setPaymentMethod(PaymentMethod paymentMethod) { this.paymentMethod = paymentMethod; } public void checkout() { if (paymentMethod == null) { System.out.println("Please select a payment method"); return; } System.out.println("Processing order..."); // 多态调用:运行时确定具体支付方式 if (paymentMethod.pay(totalAmount)) { System.out.println("Payment successful via " + paymentMethod.getPaymentType()); } else { System.out.println("Payment failed"); } } } // ========== 场景 2:日志系统 ========== interface Logger { void log(String message); void error(String message); } static class ConsoleLogger implements Logger { @Override public void log(String message) { System.out.println("[CONSOLE LOG] " + message); } @Override public void error(String message) { System.err.println("[CONSOLE ERROR] " + message); } } static class FileLogger implements Logger { private String filename; public FileLogger(String filename) { this.filename = filename; } @Override public void log(String message) { System.out.println("[FILE LOG to " + filename + "] " + message); } @Override public void error(String message) { System.out.println("[FILE ERROR to " + filename + "] " + message); } } static class DatabaseLogger implements Logger { private String connectionString; public DatabaseLogger(String connectionString) { this.connectionString = connectionString; } @Override public void log(String message) { System.out.println("[DB LOG to " + connectionString + "] " + message); } @Override public void error(String message) { System.out.println("[DB ERROR to " + connectionString + "] " + message); } } /** * 应用服务:使用多态的日志记录器 */ static class Application { private Logger logger; // 多态字段 public Application(Logger logger) { this.logger = logger; } public void start() { logger.log("Application started"); } public void processData() { try { logger.log("Processing data..."); int result = 100 / 0; // 异常 } catch (Exception e) { logger.error("Error: " + e.getMessage()); } } } // ========== 场景 3:策略模式 ========== interface SortStrategy { void sort(int[] array); } static class BubbleSort implements SortStrategy { @Override public void sort(int[] array) { System.out.println("Using Bubble Sort"); for (int i = 0; i < array.length - 1; i++) { for (int j = 0; j < array.length - 1 - i; j++) { if (array[j] > array[j + 1]) { int temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; } } } } } static class QuickSort implements SortStrategy { @Override public void sort(int[] array) { System.out.println("Using Quick Sort"); quickSort(array, 0, array.length - 1); } private void quickSort(int[] array, int low, int high) { if (low < high) { int pi = partition(array, low, high); quickSort(array, low, pi - 1); quickSort(array, pi + 1, high); } } private int partition(int[] array, int low, int high) { int pivot = array[high]; int i = low - 1; for (int j = low; j < high; j++) { if (array[j] < pivot) { i++; int temp = array[i]; array[i] = array[j]; array[j] = temp; } } int temp = array[i + 1]; array[i + 1] = array[high]; array[high] = temp; return i + 1; } } static class MergeSort implements SortStrategy { @Override public void sort(int[] array) { System.out.println("Using Merge Sort"); mergeSort(array, 0, array.length - 1); } private void mergeSort(int[] array, int left, int right) { if (left < right) { int mid = (left + right) / 2; mergeSort(array, left, mid); mergeSort(array, mid + 1, right); merge(array, left, mid, right); } } private void merge(int[] array, int left, int mid, int right) { // 归并逻辑 } } /** * 排序器:运行时切换排序策略 */ static class Sorter { private SortStrategy strategy; public void setStrategy(SortStrategy strategy) { this.strategy = strategy; } public void executeSort(int[] array) { if (strategy == null) { System.out.println("No sorting strategy set"); return; } strategy.sort(array); // 多态调用 } } // ========== 场景 4:工厂模式 + 多态 ========== interface Database { void connect(); void query(String sql); void disconnect(); } static class MySQLDatabase implements Database { @Override public void connect() { System.out.println("Connecting to MySQL..."); } @Override public void query(String sql) { System.out.println("MySQL Query: " + sql); } @Override public void disconnect() { System.out.println("Disconnecting from MySQL"); } } static class PostgreSQLDatabase implements Database { @Override public void connect() { System.out.println("Connecting to PostgreSQL..."); } @Override public void query(String sql) { System.out.println("PostgreSQL Query: " + sql); } @Override public void disconnect() { System.out.println("Disconnecting from PostgreSQL"); } } static class MongoDBDatabase implements Database { @Override public void connect() { System.out.println("Connecting to MongoDB..."); } @Override public void query(String sql) { System.out.println("MongoDB Query: " + sql); } @Override public void disconnect() { System.out.println("Disconnecting from MongoDB"); } } /** * 数据库工厂 */ static class DatabaseFactory { public static Database createDatabase(String type) { switch (type.toLowerCase()) { case "mysql": return new MySQLDatabase(); case "postgresql": return new PostgreSQLDatabase(); case "mongodb": return new MongoDBDatabase(); default: throw new IllegalArgumentException("Unknown database type: " + type); } } } /** * 数据访问层:使用多态处理不同数据库 */ static class DataAccessLayer { private Database database; public DataAccessLayer(String dbType) { this.database = DatabaseFactory.createDatabase(dbType); } public void executeQuery(String sql) { database.connect(); // 多态调用 database.query(sql); // 多态调用 database.disconnect(); // 多态调用 } } // ========== 测试所有场景 ========== public static void main(String[] args) { System.out.println("========== 场景 1:支付系统 =========="); Order order = new Order(99.99); // 使用信用卡支付 order.setPaymentMethod(new CreditCardPayment("1234-5678-9012-3456")); order.checkout(); // 切换为 PayPal order.setPaymentMethod(new PayPalPayment("user@example.com")); order.checkout(); // 切换为微信支付 order.setPaymentMethod(new WeChatPayment("13800138000")); order.checkout(); System.out.println("\n========== 场景 2:日志系统 =========="); // 使用控制台日志 Application app1 = new Application(new ConsoleLogger()); app1.start(); app1.processData(); // 切换为文件日志 Application app2 = new Application(new FileLogger("app.log")); app2.start(); app2.processData(); // 切换为数据库日志 Application app3 = new Application(new DatabaseLogger("jdbc:mysql://localhost/logs")); app3.start(); app3.processData(); System.out.println("\n========== 场景 3:策略模式 =========="); int[] data = {64, 34, 25, 12, 22, 11, 90}; Sorter sorter = new Sorter(); // 使用冒泡排序 sorter.setStrategy(new BubbleSort()); sorter.executeSort(data.clone()); // 切换为快速排序 sorter.setStrategy(new QuickSort()); sorter.executeSort(data.clone()); // 切换为归并排序 sorter.setStrategy(new MergeSort()); sorter.executeSort(data.clone()); System.out.println("\n========== 场景 4:工厂模式 =========="); // 使用 MySQL DataAccessLayer dal1 = new DataAccessLayer("mysql"); dal1.executeQuery("SELECT * FROM users"); // 切换为 PostgreSQL DataAccessLayer dal2 = new DataAccessLayer("postgresql"); dal2.executeQuery("SELECT * FROM products"); // 切换为 MongoDB DataAccessLayer dal3 = new DataAccessLayer("mongodb"); dal3.executeQuery("db.orders.find()"); } } ``` 说明: 1. **支付系统(场景 1)**:通过设置 `PaymentMethod`,动态切换支付方式(信用卡、PayPal、微信支付),展示了如何通过多态来处理不同支付方式。 2. **日志系统(场景 2)**:通过日志记录器接口 `Logger`,切换控制台日志、文件日志和数据库日志,展示多态如何适配不同日志输出方式。 3. **策略模式(场景 3)**:通过 `SortStrategy` 接口,运行时切换排序算法(冒泡排序、快速排序、归并排序),展示如何使用策略模式。 4. **工厂模式 + 多态(场景 4)**:通过 `Database` 接口,动态选择数据库(MySQL、PostgreSQL、MongoDB),展示了工厂模式与多态结合的使用。 ## **四、Java OOP 的高级特性** ### **4.1 单继承机制** ```java /** * Java 为什么不支持多重继承? * * 问题:菱形继承问题(Diamond Problem) */ public class SingleInheritanceDemo { // ========== 菱形继承问题示例(假设 Java 支持多继承) ========== /** * 假设的场景: * * A * / \ * B C * \ / * D * * 如果 B 和 C 都重写了 A 的方法,D 继承 B 和 C, * 那么 D 调用该方法时应该用哪个版本? */ static class A { public void display() { System.out.println("A"); } } // ❌ Java 不支持 // class D extends B, C { } // 编译错误 /** * Java 的解决方案:单继承 + 接口多实现 */ static class B extends A { @Override public void display() { System.out.println("B"); } } static class C extends A { @Override public void display() { System.out.println("C"); } } // ✅ D 只能选择继承一个类 static class D extends B { // 只继承 B 的实现 } /** * 单继承的优势: * * ✅ 1. 避免菱形继承问题 * ✅ 2. 简化继承关系 * ✅ 3. 降低复杂度 * ✅ 4. 提高代码可读性 */ } ``` ### **4.2 接口多实现** ```java /** * Java 通过接口实现"多重继承"的效果 */ public class MultipleInterfaceDemo { // ========== 多个接口 ========== // Flyable 接口:定义了飞行和起飞行为 interface Flyable { void fly(); default void takeOff() { System.out.println("Taking off..."); } } // Swimmable 接口:定义了游泳和潜水行为 interface Swimmable { void swim(); default void dive() { System.out.println("Diving..."); } } // Runnable 接口:定义了奔跑和冲刺行为 interface Runnable { void run(); default void sprint() { System.out.println("Sprinting..."); } } // ========== 实现多个接口 ========== /** * Duck 类实现了 Flyable, Swimmable 和 Runnable 接口 * 拥有飞行、游泳、奔跑的能力 */ static class Duck implements Flyable, Swimmable, Runnable { @Override public void fly() { System.out.println("Duck is flying"); } @Override public void swim() { System.out.println("Duck is swimming"); } @Override public void run() { System.out.println("Duck is running"); } } /** * Fish 类只实现了 Swimmable 接口 */ static class Fish implements Swimmable { @Override public void swim() { System.out.println("Fish is swimming"); } } /** * Bird 类实现了 Flyable 和 Runnable 接口 */ static class Bird implements Flyable, Runnable { @Override public void fly() { System.out.println("Bird is flying"); } @Override public void run() { System.out.println("Bird is running"); } } // ========== 接口冲突问题 ========== // 定义两个接口,它们有相同的默认方法 display interface Interface1 { default void display() { System.out.println("Interface1"); } } interface Interface2 { default void display() { System.out.println("Interface2"); } } /** * 如果两个接口有相同的默认方法,必须在实现类中显式重写 */ static class MyClass implements Interface1, Interface2 { @Override public void display() { // 必须重写以解决冲突 // 方式 1:提供自己的实现 System.out.println("MyClass"); // 方式 2:调用某个接口的默认实现 // Interface1.super.display(); // 或 // Interface2.super.display(); } } // ========== 接口继承接口 ========== interface Animal { void eat(); } interface Pet extends Animal { void play(); } interface WildAnimal extends Animal { void hunt(); } /** * 接口可以继承多个接口 */ interface Creature extends Flyable, Swimmable { void breathe(); } static class Dragon implements Creature { @Override public void fly() { System.out.println("Dragon is flying"); } @Override public void swim() { System.out.println("Dragon is swimming"); } @Override public void breathe() { System.out.println("Dragon is breathing fire"); } } // ========== 测试 ========== public static void main(String[] args) { System.out.println("========== Duck(多接口实现) =========="); Duck duck = new Duck(); duck.fly(); duck.swim(); duck.run(); duck.takeOff(); // 默认方法 duck.dive(); // 默认方法 duck.sprint(); // 默认方法 System.out.println("\n========== 多态 =========="); // Duck 可以被视为多种类型 Flyable flyable = duck; flyable.fly(); Swimmable swimmable = duck; swimmable.swim(); Runnable runnable = duck; runnable.run(); System.out.println("\n========== 接口冲突解决 =========="); MyClass obj = new MyClass(); obj.display(); System.out.println("\n========== Dragon(接口继承) =========="); Dragon dragon = new Dragon(); dragon.fly(); dragon.swim(); dragon.breathe(); dragon.takeOff(); // 继承自 Flyable dragon.dive(); // 继承自 Swimmable } } ``` 1. **多个接口:** - 定义了三个接口 `Flyable`、`Swimmable` 和 `Runnable`,它们包含了飞行、游泳、奔跑的行为,且每个接口有一个默认方法。 2. **实现多个接口:** - `Duck` 类实现了所有三个接口(`Flyable`、`Swimmable` 和 `Runnable`),具备飞行、游泳、奔跑的功能。 - `Fish` 类只实现了 `Swimmable` 接口,具备游泳功能。 - `Bird` 类实现了 `Flyable` 和 `Runnable` 接口,具备飞行和奔跑的功能。 3. **接口冲突:** - `Interface1` 和 `Interface2` 都有 `display` 方法,如果实现这两个接口,需要在 `MyClass` 中重写 `display` 方法来解决冲突,可以选择自定义实现或调用某个接口的默认实现。 4. **接口继承:** - `Creature` 接口继承了 `Flyable` 和 `Swimmable`,并定义了 `breathe` 方法,`Dragon` 类实现了 `Creature` 接口,具备飞行、游泳和呼吸的能力。 5. **多态:** - `Duck` 类对象可以被作为 `Flyable`、`Swimmable` 和 `Runnable` 类型使用,展示了接口的多态特性。 6. **测试:** - `main` 方法测试了各个场景,展示了如何使用多个接口、如何解决接口冲突以及如何利用接口继承创建多功能类。 核心概念: - **多接口实现:** 类可以实现多个接口,从而实现多重功能。 - **默认方法:** 接口可以提供默认方法,在实现类中不必实现。 - **接口冲突:** 如果多个接口定义了相同的默认方法,必须在实现类中显式重写该方法。 - **接口继承:** 接口可以继承多个接口,创建更复杂的接口层次结构。 ### **4.3 接口 vs 抽象类:** 接口(Interface): - ✅ 支持多实现 - ✅ 所有方法默认是 public abstract(JDK 8 前) - ✅ 只能有常量(public static final) - ✅ 支持默认方法和静态方法(JDK 8+) - ✅ 表示"能做什么"(能力) 抽象类(Abstract Class): - ✅ 只支持单继承 - ✅ 可以有任意访问修饰符 - ✅ 可以有实例变量 - ✅ 可以有构造器 - ✅ 表示"是什么"(本质) --- ⬅️ [[05-面向对象or面向过程|面向对象or面向过程]] 🏠 [[00-Java|00-Java]] ➡️ [[07-面向对象设计的SOLID原则|面向对象设计的SOLID原则]]