不可变类型的getter

Hug*_*ugo 1 java

我正在用Java编写一些不可变类型,并想知道如何命名访问器方法.Java Bean规范说访问者的名称应该是getX或isX,但由于字段是final,因此没有setter,字段更像属性而不是属性.

因为我更喜欢命名getter方法,如:

public T x()
Run Code Online (Sandbox Code Playgroud)

而不是

public T getX()
Run Code Online (Sandbox Code Playgroud)

请注意作为一个例子:

public int java.lang.String#length()
Run Code Online (Sandbox Code Playgroud)

(这可能是在Java历史的早期指定的,所以那些惯例还没有.)

不可变对象暴露意味着通过我试图命名为动词的方法创建自己的修改版本而不是MyObject MyObject#setX(),这应该限制用户调用setX()并认为对象已更改的风险.所以:MyObject MyObject#shine(newShineLevel).

但这并不总是那么容易.你如何命名一个方法来调整一个矩形以外的矩形Rectangle.setUpperLeft()Rectangle.adjustUpperLeft也许,但现在我们正在摆脱惯例.

我想这个问题与所有语言都有关系,但这个问题尤其涉及Java.

tgd*_*ies 7

如果这些类可以与任何基于反射的框架一起使用,那么最好不要使用getX约定.例如,通过表达式"xy"访问JSP和其他模板系统中的属性需要该对象具有方法getY().


Yuv*_*dam 6

即使对于不可变类型,该惯例getX()仍然存在.一些例子:

  • java.lang.Integer.getInteger()
  • java.lang.Boolean.getBoolean()

确实存在许多例子java.lang.String.length(),但常见的惯例是使用getX.正如下面的答案中所提到的,将原子获取操作和对数据进行一些计算的方法分开是至关重要的.

还值得一提的是,许多框架中的普通java bean依赖于getter/setter方便地命名为getXsetX的事实.

  • Ehm,`getInteger`和`getBoolean`不是getter(它们接受参数并且是静态的),如果你看一下这些类的非静态方法,你会发现`booleanValue`,`intValue`等.另外,具有访问器方法的整个要点是,您希望*能够隐藏,如果值存储在字段中,或者它是聚合值,以便您可以在没有接口的情况下更改实现.当然,极其计算密集的计算不应该假装成访问器,但是字段访问和简单计算都是隐藏在访问器后面的良好候选者. (3认同)
  • 为什么知道计算值和"存储"值之间的差异很重要?是不是那种让访问器方法开始的原因,而不是直接暴露内部变量 (2认同)

Oll*_*lly 6

Java中用于访问类属性的约定 - 包括不可变类 - 是使用getset前缀,所以我建议使用public final T getX().

length()不调用String上的方法的原因getLength()是因为没有length在String类上调用的属性.

  • 它可能在内部被称为计数或大小(我相信它是计数),但我很确定它将信息存储在某处,所以我不会说length()是一种执行计算的方法.即使它没有被存储,在命名中暴露这个事实也会基本暴露实现细节,这会以某种方式破坏封装,所以我认为这种命名方式无论如何都是有缺陷的 (2认同)

gus*_*afc 6

当我这么说时,人们往往会否决我,但get前缀实际上仅在您编写 bean 时才是强制性的。有很多的例子在那里get使用。不仅String.length()。您可以在原始包装类 ( intValue(), doubleValue(), booleanValue(), ...)、枚举 ( name()and ordinal()) 和集合 ( size()) 中找到它,并且注解的设计方式似乎也鼓励了get-less 风格。(Josh Bloch 在 Effective Java 中涵盖了这个主题,并提倡可读性更强的get风格,除非你真的在写一个 bean。)

所以:使用get前缀,您的对象可以用作bean。放弃它,你的代码会变得更容易阅读。由您来决定您认为什么更重要。

我自己,即使我不喜欢它,我通常也会使用前缀,因为 Eclipse 会自动为我生成它:)

  • +1。在 Google Collections 中,我遵循 Josh 的建议——当你有一个真正的 get-and-set 对时使用 get,例如 Map.Entry 有 getValue() 和 setValue()。并且在它太奇怪的时候使用 get,例如 Map.Entry 的第三个方法是 getKey() 因为 key() 会突出。除此之外, get 是一个绝对无用的前缀。有人真的希望他们不得不说 Iterator.getNext() 吗? (3认同)