从 Java 基础到掌握 — 第 3 集
设计对象、封装和不可变值
该博客上撰写的文章是出于教学目的而创建的。 另外,文章中的信息可能不正确,请谨慎。
对象将相关状态和行为绑定在单个边界内。 封装并不是无条件隐藏字段,而是将规则放入类中,以便只能创建有效的状态。
使用构造函数创建有效对象
public final class Player {
private final String name;
private int health;
public Player(String name, int health) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("name is required");
}
this.name = name;
this.health = Math.max(0, health);
}
public void takeDamage(int amount) {
if (amount > 0) {
health = Math.max(0, health - amount);
}
}
public int getHealth() {
return health;
}
}
外界无法直接改变健康;它仅通过名为 takeDamage 的规则来更改它。 构造函数完成的对象满足名称和健康有效的条件。
引用可以指向同一个对象
Player first = new Player("Rose", 100);
Player second = first;
second.takeDamage(20);
System.out.println(first.getHealth()); // 80
在第二个例子中,对象没有被复制,但指向同一个 Player 的引用被复制。 如果需要独立副本,则必须明确设计要复制哪些字段。
创建不可变的值
public final class ItemKey {
private final int id;
private final String grade;
public ItemKey(int id, String grade) {
this.id = id;
this.grade = grade;
}
}
如果将字段设置为最终字段并且不提供更改方法,则其状态在创建后不会更改。 但是,如果该字段是可变集合,则应考虑防御性复制或只读视图。
对象设计的重点不是同时创建 getter 和 setter。 谁可以改变状态以及必须始终维持什么条件通过类的公共方法来表达。