【Effective Java 15】使类和成员的可访问性最小化

区分一个组件设计得好不好,取决于它对于外部的其他组件而言,是否隐藏了其内部数据和其他实现细节。设计良好的组件会隐藏所有的实现细节,把 API 与实现清晰地隔离开来。然后,组件之间只会通过 API 进行通信,一个模块不需要知道其他模块的内部工作情况。这个概念被称为信息隐藏(information hiding)或封装(encapsulation),是软件设计的基本原则之一。

为什么需要信息隐藏:

  1. 可以有效地接触组成系统的各组件间的耦合关系,即解耦(decouple)
  2. 减少维护负担,程序员可以更快地理解这些组件
  3. 提升软件的可重用性
  4. 降低了构建大型系统的风险,当整个系统不可用时,其某些组件依然可能是可用的。

1. 最小化可访问性基本规则

  • 尽可能地使每一个类或成员不被外界访问,即应该使用与你正在编写的软件的对应功能相一致的,尽可能最小的访问级别。
  • 子类中的访问级别不允许低于超类中的访问级别,以确保任何可用超类的实例的地方也可以使用子类(里氏替换原则)
  • 不能为了测试方便而随意改变类成员的可访问性
  • 公有类的实例域不能公有,除非该实例域是 final 的。一旦实例域称为公有,就等于放弃了对存储在这个域中的值进行限制的能力。此外,这还将导致线程安全问题。即便实例域是 final 的,并且引用不可变的对象,但当把这个域变为公有时,也就放弃了 “切换到一种新的内部数据表示法” 的灵活性

2. final 静态域的注意事项

让类具有公共的静态 final 数组域,或者返回这种域的访问方法,是错误的。

public static final Integer[] VALUES = {...}; // 错误, VALUES 引用不可修改,但数组中的值可以修改
// 正确做法 1: 使用不可变容器
private static final Integer[] PRIVATE_VALUES = {...}; 
public static final List<Integer> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

// 正确做法 2: 返回克隆对象
private static final Integer[] PRIVATE_VALUES = {...}; 
public static final Integer[] values() {
    return PRIVATE_VALUES.clone();
}

posted on 2022-04-15 19:26  Silgm  阅读(45)  评论(0)    收藏  举报

导航