即使我知道我永远不需要它,在我的对象中包含一个setter也是一种好习惯

时间:2013-08-30 23:07:57

标签: java object setter getter

今天出现了一个有趣的问题。对于一个我知道在构造函数之后永远不需要重新设置的字段的setter来说,这是一个好习惯吗?

P.S。当然,我理解使用私有字段和getter与公共字段的原因,这是有道理的,但应该如果我不打算使用它,我真的会成为一个setter吗? / p>

P.P.S。具体指Java,虽然它应该对什么平台无关紧要。

3 个答案:

答案 0 :(得分:4)

通过不创建setter并且只允许通过构造函数设置字段,您创建了一个不可变字段。一旦创建了类的实例,该值就永远不会改变。

注意:如果getter返回的值本身是可变的,则上述语句将不成立。比如说,如果返回ArrayList的实例,有人可以使用该引用添加和删除该列表中的项目。看java.util.Collections.unmodifiableList来解决这个问题。如果您在getter中返回它,即使java.util.Date也可以更改。要解决此问题,您可以使用JodaTime(或其他类似的第三方日期类),或等待Java 8。

在我的谦逊(以及其他并非总是如此谦逊)的观点中,可模仿性是一件很棒的事情,它可以使软件减少错误并且更容易维护。

答案 1 :(得分:2)

这取决于。

如果您的类是导出的API的一部分,并且您有理由相信您的API的客户将有机会使用setter,那么包含一个可能是合理的。

但这是关于吸气剂和制定者的真相。

如果你的班级有他们,那么你的班级是可变的。可变数据和可变对象就是它们的本质。如果您的设计意图指定此API将始终是单线程的,那么您没有问题。

但是,即使在单线程应用程序中,您也应该尽可能地创建不可变对象。不可变对象的缺点是它们中没有getter和setter的作用(**见注释)。

折衷方案是Builder Pattern(Bloch等,Effective Java 2nd Ed。)。在这个模式中,您使用一个可变的辅助对象来设置对象的字段......然后当您准备好时,您的帮助对象使用您设置的数据来创建所需对象的不可变实例。 / p>

当您的需求很简单并且不关心争用或并发时,请使用可变对象。但请记住,你的对象越可变,就越难以推断它的状态。并且越难以推断其状态,执行不变量和维护安全性可能更加困难。只有一个状态的对象几乎可以解决所有这些问题。特别是如果你的类是一个值类,你应该尽可能地创建不可变对象。

(**)注意:当然,可以为不可变类设置setter。在这种情况下,setter实例化一个新的不可变对象,从而保持其不变性。 String类依赖于这种策略。

答案 2 :(得分:1)

  

为一个字段创建一个setter是不错的做法我知道我永远不需要在构造函数之后重新设置

如果您事先知道,那么,请务必将其写入您的代码中。创建该字段final,然后你就不会有任何疑问,因为编译器本身不允许你定义一个setter。

这可以避免编写方法“因为它可能是预期的”,并且在我看来也是保持代码清洁和可验证的一步。你正在宣告事物,这也消除了测试价值不变性的必要性。