封装的本质是隐藏内部实现细节,仅暴露安全、可控的访问接口;java中通过private修饰字段、构造器校验初始化、getter/setter方法控制读写来实现。

封装是面向对象的三大核心特性之一,它的本质是**隐藏内部实现细节,仅暴露安全、可控的访问接口**。在 Java 中,主要通过 访问修饰符(private / protected / public)、getter/setter 方法 和 构造器控制初始化逻辑 来体现。
用 private 限制字段直接访问
把类的属性设为 private,外部代码就无法直接读写,避免了非法或不一致的状态。比如一个表示银行账户的类:
public class BankAccount {
private String accountNumber;
private double balance;
// 构造器初始化,确保账户号非空
public BankAccount(String accountNumber, double initialBalance) {
if (accountNumber == null || accountNumber.trim().isEmpty()) {
throw new IllegalArgumentException("账号不能为空");
}
this.accountNumber = accountNumber;
this.balance = Math.max(0, initialBalance); // 余额不能为负
}
}
此时,accountNumber 和 balance 无法被外部直接修改,如 account.balance = -1000; 会编译报错。
提供受控的 getter 和 setter 方法
通过 public 方法暴露“读”和“写”的能力,但可在其中加入校验、转换或日志等逻辑:
-
getBalance()可以返回只读副本(如对 BigDecimal 返回新对象) -
deposit(double amount)比简单 setter 更语义化,且能校验金额有效性 -
setAccountNumber()通常不提供,因为账号应不可变;若需修改,可设计为changeAccountNumber(newNum, auth)并加权限检查
示例:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
public double getBalance() {
return balance; // 只读访问
}
public void deposit(double amount) {
if (amount this.balance) {
return false;
}
this.balance -= amount;
return true;
}
使用 final 和不可变设计强化封装
对不需要修改的字段用 final 修饰,并配合私有构造 + 无 setter,可构建不可变对象,天然线程安全:
public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = Objects.requireNonNull(name);
this.age = Math.min(Math.max(0, age), 150); // 合理范围约束
}
// 只有 getter,没有 setter
public String getName() { return name; }
public int getAge() { return age; }
}
一旦创建,Person 的状态就完全固定,调用方无法绕过逻辑篡改数据。
封装不只是“加 private”,而是设计契约
真正体现封装思想的,是类对外承诺什么、隐藏什么、如何保证不变量:
- 隐藏字段是手段,不是目的;重点是不让外部破坏对象一致性
- 方法命名要体现意图(如
withdraw()而非setBalance(...)) - 异常处理、边界检查、日志埋点都属于封装内的职责
- 内部辅助方法(如
validatePin())应设为 private,不暴露给使用者
封装让类成为一个可靠、自洽的“黑盒”,使用者只需关心它能做什么,无需知道怎么做 —— 这正是可维护性与协作效率的基础。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










