---
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 调用不能忘 │
│ │
│ 多态:父类引用指向子,编译看左运行右 │
│ │
│ ───────────────────────────────────────────────── │
│ │
│ 多态三要素: │
│ ① 有继承 ② 有重写 ③ 父类引用指向子类对象 │
│ │
│ 方法重写规则(两同两小一大): │
│ • 两同:方法名、参数列表相同 │
│ • 两小:返回类型 ≤ 父类、异常 ≤ 父类 │
│ • 一大:访问权限 ≥ 父类 │
│ │
└─────────────────────────────────────────────────────────────────┘
```