核心思想: OOP不是语法糖,而是建模现实世界的思维范式。三大特征共同解决了复杂性管理问题。
🔒 1、封装 (保护内部)
本质定义: "Tell, Don't Ask"原则:对象暴露行为(方法),隐藏状态(数据)。不是简单的"private字段+public getter/setter",而是职责边界的划分。
关键认知:
- ✅封装的是变化: 当业务规则变化时(如余额计算逻辑),客户端代码无需修改
- ✅ 访问修饰符是手段,不是目的:
private/protected/public服务于封装原则 - ❌ "用private+getter/setter就是封装" → ✅ "封装是暴露行为,不是暴露数据"
// 反模式:伪封装(只是字段私有化)
public class BadBankAccount {
private double balance;
public double getBalance() { return balance; }
public void setBalance(double balance) { this.balance = balance; }
}
// 真正的封装:暴露业务行为,隐藏实现细节
public class BankAccount {
private double balance;
// 暴露业务行为,而非数据
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("金额必须为正");
this.balance += amount;
}
public boolean withdraw(double amount) {
if (amount <= 0) throw new IllegalArgumentException("金额必须为正");
if (balance < amount) return false;
this.balance -= amount;
return true;
}
// 查询行为,而非直接暴露状态
public double getAvailableBalance() {
return balance * 0.9; // 假设10%是冻结资金
}
}
🧬2、继承 (复用代码)
本质定义
"is-a"关系的代码表达,但更准确地说是契约复用。继承的目的是行为复用,而非仅仅是代码复用。
关键认知:
- ✅ 继承是强耦合:子类依赖父类的实现细节,违反开放-封闭原则
- ✅ 方法重写是契约:子类必须满足父类的前置/后置条件(Liskov原则)
- ✅ Java单继承的哲学:避免菱形问题,强制设计者思考"真正"的is-a关系
// 继承的正确使用:Liskov替换原则
public abstract class PaymentMethod {
public abstract boolean processPayment(double amount);
// 模板方法模式:继承的核心价值
public final boolean executePayment(double amount) {
if (!validatePayment(amount)) {
return false;
}
return processPayment(amount);
}
protected boolean validatePayment(double amount) {
return amount > 0;
}
}
public class CreditCardPayment extends PaymentMethod {
private String cardNumber;
@Override
public boolean processPayment(double amount) {
// 信用卡特定逻辑
System.out.println("处理信用卡支付: " + amount);
return true;
}
// 重写父类验证逻辑
@Override
protected boolean validatePayment(double amount) {
return super.validatePayment(amount) && amount <= 10000; // 信用卡限额
}
}
// 使用:完全不需要知道具体子类
public class PaymentProcessor {
public void process(PaymentMethod method, double amount) {
boolean success = method.executePayment(amount);
System.out.println("支付结果: " + success);
}
}
🤡3、多态 (灵活扩展)
本质定义
同一接口,多种实现。 多态的核心是运行时绑定,让程序在编译期不知道具体类型,而在运行时动态决定行为
关键认知
- ✅ 多态 = 向上转型 + 动态绑定:父类引用指向子类对象,运行时JVM决定调用哪个方法
- ✅ 方法表(vtable)机制:JVM通过对象头中的类指针找到方法表,实现动态分派
- ✅ 多态是解耦的核心:高层模块依赖抽象,不依赖具体实现
- ✅
@Override注解的价值:编译期检查,防止错误重写
// 多态的三种实现方式
// 1. 继承 + 方法重写(最常见)
public class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("汪汪!");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("喵喵!");
}
}
// 2. 接口实现(更推荐)
public interface Flyable {
void fly();
}
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟儿飞翔");
}
}
public class Airplane implements Flyable {
@Override
public void fly() {
System.out.println("飞机起飞");
}
}
// 3. 方法重载(编译时多态,非OOP核心)
public class Calculator {
public int add(int a, int b) { return a + b; }
public double add(double a, double b) { return a + b; }
}
// 多态的真正威力:开闭原则
public class Zoo {
// 可以接受任何Animal子类,无需修改代码
public void makeAllSounds(List<Animal> animals) {
for (Animal animal : animals) {
animal.makeSound(); // 运行时决定调用哪个方法
}
}
// 通过接口实现更灵活的多态
public void makeAllFly(List<Flyable> flyables) {
for (Flyable flyable : flyables) {
flyable.fly();
}
}
}