不可变类型:公共最终字段与getter

Dan*_*iel 53 java immutability

我需要一个小的Container-Class来存储一些应该是不可变的字符串.由于String本身是一个不可变类型,我想到了类似的东西:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

许多人似乎完全反对使用公共字段,而是使用Getters.恕我直言,在这种情况下,这只是样板,因为String本身是不可变的.

我可能在这个问题上缺少的其他想法?

Pet*_*rey 54

我会做你认为最简单和最清楚的事情.如果您有一个仅由有限数量的类使用的数据值类.特别是一个包本地类.那么我会避免使用getter/setter并使用package local或public字段.

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

  • 谢谢彼得,我喜欢你的用例差异化. (2认同)
  • 此外,除非这是一个API,否则你可以使用Eclipse或Intellij稍后在需要getter的时候重构代码.重构>封装字段.YAGNI. (2认同)

Dan*_*ral 25

问题是统一访问原则.您可能稍后需要进行修改,foo以便通过方法获取而不是修复,如果您公开了字段而不是getter,则需要中断API.

  • 允许Immu的子类是我想要避免的,因为这可能导致可变的子类. (6认同)
  • 此外,您将放弃使用一些自定义get方法子类化"Immu"的可能性. (2认同)

emo*_*ory 14

为什么不

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 ; }
       }
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*isA 6

我在home项目中使用public-final-field(anti?)模式,这些模式基本上是带有构造函数的不可变数据结构,以及equals(),hashCode(),toString()等绝对基础知识. .(我正在避免使用"struct"这个词,因为它有各种不同的语言解释.)

我不会将这种方法带到其他人的代码库(工作,公共项目等),因为它可能与其他代码不一致,并且像Of In Rome或Least Surprise这样的原则优先考虑.

也就是说,关于Daniel C. Sobral和aioobe的答案,我的态度是,如果由于不可预见的发展而导致课堂设计成为一个问题,那么在IDE中将这些字段私有化并添加访问器的工作时间为30秒.超过5或10分钟来修复损坏的引用,除非有数百个.任何因此而失败的东西都会得到它应该首先进行的单元测试.:-)

[编辑:有效的Java非常坚决反对这个想法,同时注意到它对不可变的字段"危害较小".


Man*_*arm 5

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

  • public final 对于不可变类型,看起来最干净。
  • 即使不是故意的,访问者也可能会更改可变类型-在并发环境中,这可能会引起很多麻烦。
  • 不能有无参数的构造函数。如果您需要工厂方法(例如,用于LMAX Disruptor),则这很重要。以类似的方式,通过反射实例化对象变得更加复杂。
  • 吸气剂和塞特剂可能会有副作用。使用可以public final清楚地告诉程序员,没有隐藏的魔术正在发生,并且对象本质上是愚蠢的:)
  • 您不能将包装器或派生类实例返回给访问器。再说一遍,这是您应该为字段分配值的一些知识。在我看来,容器类不应关注返回给谁的东西。

如果您正在开发中,并且没有指导方针可以阻止您,并且该项目是孤立的,或者您可以控制所有建议使用public final的不可变类型的项目。如果您决定以后需要使用吸气剂,则Eclipse提供Refactor-> Encapsulate Field...自动创建吸气剂并调整对该字段的所有引用。