第 16 章:封装
学习目标
- 理解封装的本质和价值
- 掌握四种访问修饰符
- 学会 JavaBean 规范
一、什么是封装?
封装 = 把数据藏起来,对外暴露受控的访问方式。
反例:没有封装
java
public class User {
public String name; // ❌ 外部可直接修改
public int age;
}
User u = new User();
u.name = ""; // ❌ 可以设置为空字符串
u.age = -100; // ❌ 可以设置为负数正例:封装后
java
public class User {
private String name; // ① 私有字段
private int age;
public String getName() { return name; }
public void setName(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("姓名不能为空");
}
this.name = name;
}
public int getAge() { return age; }
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄不合法");
}
this.age = age;
}
}二、四种访问修饰符
| 修饰符 | 同类 | 同包 | 子类 | 其他包 |
|---|---|---|---|---|
private | ✅ | ❌ | ❌ | ❌ |
| 默认(无) | ✅ | ✅ | ❌ | ❌ |
protected | ✅ | ✅ | ✅ | ❌ |
public | ✅ | ✅ | ✅ | ✅ |
三、JavaBean 规范
JavaBean 是符合特定约定的类:
- 类必须是
public - 字段必须是
private - 必须有无参构造器
- 用
getter/setter暴露字段
java
public class User implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
public User() { } // ① 无参构造器
public Long getId() { return id; } // ② getter
public void setId(Long id) { this.id = id; } // ③ setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}IDEA 右键 → Generate → Getters and Setters 一键生成。
四、封装的实际价值
4.1 数据校验
java
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄不合法");
}
this.age = age;
}4.2 计算属性
java
public class Circle {
private double radius;
public double getArea() { // ① 计算属性,无需字段
return Math.PI * radius * radius;
}
}4.3 延迟初始化
java
public class Config {
private Properties props;
public Properties getProps() { // ② 用到时才加载
if (props == null) {
props = loadProps();
}
return props;
}
}4.4 不变性
java
public final class ImmutableUser { // ① final 类不可继承
private final String name; // ② final 字段不可修改
private final int age;
public ImmutableUser(String name, int age) {
this.name = name;
this.age = age;
}
// 只有 getter,没有 setter
public String getName() { return name; }
public int getAge() { return age; }
}
String、Integer等都是不可变对象(详见第 23 章)。
五、本章小结
| 要点 | 关键 |
|---|---|
| 封装本质 | 把数据藏起来,对外暴露受控方法 |
| 访问修饰符 | private / 默认 / protected / public |
| JavaBean 规范 | private 字段 + getter/setter + 无参构造 |
| 封装的价值 | 校验、计算属性、延迟初始化、不变性 |
动手练习
练习 1:基础题
设计一个 BankAccount 类(银行账户),封装:
java
private String accountNumber // 账号(不可修改)
private String owner // 户主(不可修改)
private BigDecimal balance // 余额(只能通过 deposit/withdraw 修改)
public void deposit(BigDecimal amount) // 存款(必须 > 0)
public void withdraw(BigDecimal amount) // 取款(必须 <= balance)下一章:第 17 章:继承 →