不可变类型的getter

时间:2009-11-05 12:16:08

标签: java

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

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

public T x()

而不是

public T getX()

请注意作为一个例子:

public int java.lang.String#length()

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

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

但这并不总是那么容易。您如何命名一种方法来调整Rectangle.setUpperLeft()以外的矩形中的端点? Rectangle.adjustUpperLeft也许,但现在我们正在远离惯例。

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

6 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:6)

即使对于不可变类型,约定getX()仍然存在。一些例子:

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

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

另外值得一提的是,许多框架中的普通java bean依赖于getter / setter方便地命名为 getX setX 这一事实。

答案 2 :(得分:6)

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

String上的length()方法未被调用getLength()的原因是因为String类上没有名为length的属性。

答案 3 :(得分:4)

当我这样说时,人们倾向于向我投票,但get前缀实际上只是在写一个bean时才是强制性的。有许多示例表明使用get 。不仅String.length()。您可以在原始包装类(intValue()doubleValue()booleanValue(),...),枚举(name()ordinal())和集合({ {1}})和注释的设计方式似乎也鼓励了size() - 更少的风格。 (Josh Bloch介绍了Effective Java中的主题,并提倡更具可读性get - 更少样式,除非您实际编写bean。)

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

我自己,我经常使用前缀,即使我不喜欢它,只是因为Eclipse为我自动生成它:)

答案 4 :(得分:0)

我坚持使用“获取”约定只是因为有很多其他工具可以使用它。例如,Jakara Commons BeanUtils。如果您具有正确的命名,则许多工具/库将默认工作,但如果您偏离了bean访问器约定,则需要配置。

我并不反对你推理偏离的说法,我认为从长远来看,你可能会更好地坚持使用get / set约定。

答案 5 :(得分:0)

使用get是一个好主意 - 从不强制使用,但人们会自动知道它是什么。

Get并不意味着你将它作为一个成员变量,实际上它应该隐藏这个事实。它可以轻松地访问计算值。

size(),length()等是在Borland发现他们需要get / set概念来实现他们的GUI构建器之前创建的(我不确定是谁提出了这个想法,但这就是原因)。

intValue,doubleValue等不是getter,它们是转换器,因此命名不同。

现在,所有这一切,如果您真的想使用x或getX,那么这是您的选择。大多数体面的工具集不再需要getter和setter,他们会使用注释 - 只需准备好让几个人多花几秒钟输入“get”然后输入“ctrl-space”而不是找到他们之后的内容