理解封装的核心思想:数据与行为的统一 + 信息隐藏
掌握在 Java 中通过 访问修饰符、getter/setter 实现封装
能够设计安全、可维护、高内聚的类结构
了解封装的优势与潜在代价,避免过度或不足封装
封装(Encapsulation) 是面向对象编程(OOP)的四大基本原则之一。它的核心理念是:
“将数据(属性)和操作数据的方法(行为)捆绑在一个单元(类)中,并对外隐藏内部实现细节。”

类比理解:胶囊
就像药片把有效成分包裹在胶囊壳内:
你不需要知道药物如何合成
你只需按说明服用(调用公共方法)
制造商可以随时改进配方(内部实现),只要服用方式不变
Java 通过以下机制实现封装:
基础示例:程序员类
class Programmer {
// 1. 数据私有化
private String name;
// 2. 提供受控访问
public String getName() {
return name;
}
public void setName(String name) {
// 可在此加入验证逻辑(如非空检查)
if (name != null && !name.trim().isEmpty()) {
this.name = name.trim();
} else {
throw new IllegalArgumentException("姓名不能为空");
}
}
}
public class Main {
public static void main(String[] args) {
Programmer p = new Programmer();
p.setName("张三");
System.out.println("姓名 => " + p.getName()); // 输出:姓名 => 张三
}
}关键点:
外部无法直接写
p.name = "李四"(编译错误)所有修改必须通过
setName(),确保数据合法性
数据验证与业务逻辑
封装不仅是“加 getter/setter”,更是保障对象状态一致性的手段。
示例:银行账户类
class BankAccount {
private String accountNumber;
private double balance;
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
setBalance(initialBalance); // 使用 setter 初始化
}
public double getBalance() {
return balance;
}
// 不提供 setBalance 公开方法!防止随意修改余额
private void setBalance(double balance) {
if (balance < 0) {
throw new IllegalArgumentException("余额不能为负数");
}
this.balance = balance;
}
// 提供业务方法:存款
public void deposit(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("存款金额必须大于 0");
}
this.balance += amount;
}
// 提供业务方法:取款
public void withdraw(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("取款金额必须大于 0");
}
if (amount > balance) {
throw new IllegalStateException("余额不足");
}
this.balance -= amount;
}
public String getAccountNumber() {
return accountNumber; // 账号只读,不提供 setter
}
}安全设计:
余额不能被直接设置
所有资金变动必须通过
deposit()/withdraw()完成账号一旦创建不可更改(只读)
重要提醒:不要为了封装而封装!
如果某个字段天然无需验证(如
id、createdAt),且确定不会变更行为,可考虑简化设计。
默认将字段设为 private除非有充分理由(如工具类常量可用 public static final)
getter/setter 不是必须的
只读属性:只提供 getter
内部状态:不提供任何访问器
业务行为:用 deposit() 代替 setBalance()
在 setter 中加入验证逻辑
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄必须在 0~150 之间");
}
this.age = age;
}避免“贫血模型”不要只写 getter/setter 而无业务方法。好的封装类应包含行为,而不仅是数据容器。
封装 = 数据私有化 + 受控访问
核心目的:保护对象内部状态,提升系统健壮性
实现方式:private 字段 + public 方法(含验证)
封装不是目的,而是实现高内聚、低耦合设计的手段
合理封装让代码更安全、更易维护、更易测试
如果一个类的所有字段都是 public,它是否违反了封装原则?为什么?
在什么情况下,你可以不为私有字段提供 setter 方法?请举例说明。
如何在保持封装的同时,允许子类访问父类的某些内部状态?