不可变types:public final字段与getter

我需要一个小的容器类来存储一些应该是不可变的string。 由于string本身是一个不可改变的types,我想到了这样的事情:

public final class Immu { public final String foo; public final String bar; public Immu(final String foo, final String bar) { this.foo = foo; this.bar = bar; } } 

许多人似乎反对使用公共领域,而是使用Getters。 恕我直言,这只是在这种情况下的样板,因为string本身是不可变的。

其他的想法,我可能会错过这一个?

我会做你认为最简单,最清楚的事情。 如果您有一个数据值类,只有受限数量的类使用。 特别是一个包的本地类。 那么我会避免getter / setter和使用包本地或公共领域。

如果你有一个你希望其他模块/开发人员使用的类,那么从长远来看,遵循getter / setter模型可能是一个更安全的方法。

问题是统一的访问原则。 你可能以后需要修改foo以便通过方法获得它,而不是被修复,如果你暴露了field而不是getter,那么你需要打破你的API。

为什么不

 interface Immu { String getA() ; String getB ( ) } Immu immu ( final String a , final String b ) { /* validation of a and b */ return new Immu ( ) { public String getA ( ) { return a ; } public String getB ( ) { return b ; } } } 

我在家庭项目上使用public-final-field(anti?)模式,这些模式基本上是一个带有构造函数的不可变数据结构,以及像equals(),hashCode(),toString()等绝对基础。 (由于各种不同的语言解释,我避免使用“struct”这个词。)

我不会把这个方法带到别人的代码库(工作,公共项目等),因为它可能会与其他代码不一致,像“在罗马时间”或“最less惊喜”这样的原则是优先的。

这就是说,关于Daniel C. Sobral和aioobe的回答,我的态度是,如果由于不可预见的事态发展而导致课程devise成为一个问题,那么在IDE中需要30秒的时间将领域私有化并添加访问器,比5或10分钟来修复破碎的参考,除非有数百个。 任何因此而失败的东西都会得到应该具有的unit testing。:-)

[编辑:有效的Java是坚决反对这个想法,同时指出它在不可变的领域是“有害的”。]

如果有人打算通过API使用你的代码,这是不是很清楚。 如果您稍后需要,您也错过了validationinput的机会。

我发现这个线程希望得到一些实际的论点,但是我在这里看到的答案并没有帮到我太多。 经过更多的研究和思考,我认为以下几点必须考虑:

  • public final看起来最清洁的不可变types。
  • 可变types可能被访问者改变,即使这并不意味着 – 在并发环境中,这可能会导致很多头痛。
  • 不能有无参数的构造函数。 如果您需要工厂方法(例如用于LMAX干扰器),这是重要的。 以类似的方式通过reflection实例化对象变得更加复杂。
  • 吸气剂和制剂可能有副作用。 使用public final清楚地告诉程序员,没有隐藏的魔法发生,对象本身愚蠢:)
  • 您不能将包装器或派生类实例返回给访问器。 然后再次,这是你应该知道什么时候该领域的价值。 在我看来,集装箱class不应该关心回到谁身上。

如果你是在开发中,没有任何指导方针阻止你,项目是孤立的,或者你可以控制所有涉及到的项目,我build议使用public final作为不可变types。 如果您决定以后需要getter,Eclipse会提供Refactor – > Encapsulate Field... ,它会自动创build这些Encapsulate Field... ,并调整对该字段的所有引用。