欢迎光临散文网 会员登陆 & 注册

java 核心技术-12版 卷Ⅰ- 4.3.8 封装的优点

2023-03-20 23:00 作者:CC挑灯夜读_谷  | 我要投稿

原文:    

    最后再仔细看一下非常简单的 getName 方法、getSalary方法和getHireDay方法。

这些都是典型的访问器方法。由于它们只返回字段的值,因此又被成为字段访问器(field accessor)。

    如果将name 、salary 和 hireDay字段标记为公共,而不是编写单独的访问器方法,不是更容易一些吗?

    不过,name 是一个只读字段,一旦在构造器中设置,就没有办法能够修改这个字段。这样我们可以确保name字段不会受到外界的破坏。

    虽然salary 不是只读字段,但是它只能用raiseSalary方法修改。具体地,如果这个值出现了错误,那么只需要调试这个raiseSalary方法就可以了。如果salary字段是公共的,破坏这个字段值的罪魁祸首有可能出没在任何地方(那就很难调试了)。

    有些时候,可能想要获得或设置实例字段的值,那么你需要提供下面三项内容:

  • 一个私有的实例字段;

  • 一个公共的字段访问器方法;

  • 一个公共的字段更改器方法。

    这样做要比提供一个简单的公共实例字段复杂些,但有很多明显的好处。

    首先,可以改变内部实现,而不影响该类方法之外的任何其他代码。例如,如果将存储姓名的字段改为:

    那么getName方法可以改为返回

    这个修改对于程序的其余部分是完全不可见的。

    当然,为了进行新旧数据表示之间的转换,访问器方法和更改器方法可能需要做许多工作。这将为为我们带来第二点好处:更改器方法可以完成错误检查,而只对字段赋值的代码不会费心这么做。例如,setSalary方法可以检查工资是否小于0.

    警告:注意不要编写返回可变对象引用的访问器方法。在本书之前的一版中,我们的Employee类就违反了这个设计原则,其中getHireDay方法返回了一个Date对象:

    LocalDate类没有更改器方法,与之不同,Date类有一个更改器方法setTime,可以设置毫秒数。

    Date 对象是可变的,这一点破坏了封装性。如下:

    出错的原因很微妙。d 和 em2 的hireDay 指向了同一个对象。因此,对d修改的时候, hireDay 也受到了影响。可以回忆一下之前咱们提到的对象引用的相关内容

    如果需要返回一个可变对象的引用,首先应该对它进行克隆(clone)。对象克隆是指存放在另一个新位置上的对象副本。有关对象克隆的详细内容将在第6章中进行讨论。下面是修改后的代码:

这里有一个经验,如果需要返回一个可变字段的副本,就应该使用clone


个人建议

    对于这个代码,用clone 也好,用其他方式也好,总之,要让return 的可变对象不能与封装起来的信息指向同一个对象,否则对象的指针将被泄漏,就像你的密码被泄漏一样危险。同理,其实本代码中,构造器那里也是一样防止泄漏。

具体到Date 类,也可以用以下方式获得Date 的同值,不同指向的新实例。这种方式不需要强转,会更加友好

    


java 核心技术-12版 卷Ⅰ- 4.3.8 封装的优点的评论 (共 条)

分享到微博请遵守国家法律