Java:不可变类的伪setter方法

Jas*_*n S 14 java immutability

假设我在Java中有一个具有不可变数据的类Foo:

class Foo {
    final private int x;
    public int getX() { return this.x; }
    final private OtherStuff otherstuff;
    public Foo(int x, OtherStuff otherstuff) { 
       this.x = x;
       this.otherstuff = otherstuff;
    }   
    // lots of other stuff...
}
Run Code Online (Sandbox Code Playgroud)

现在我想添加一个实用程序方法,该方法创建一个具有相同状态但具有新值x的"兄弟"值.我可以称之为setX():

class Foo
{
    ...
    Foo setX(int newX) { return new Foo(newX, this.otherstuff); }
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是语义与setX()可变bean对象的标准setter约定不同,所以不知怎的,这感觉不对.

这种方法的最佳名称是什么?

我应该把它withX()或者newX()还是其他什么东西?


编辑:在我的情况下的额外优先级:我有脚本客户端(通过JSR-223和我导出的对象模型),可以轻松获取Foo对象.然而,调用构造函数或创建构建器或其他任何东西都很麻烦.因此,我希望提供此方法以方便脚本编写客户端.

DNA*_*DNA 14

withX() 听起来不错,因为它是一些用于某些Builder模式的约定.

这更像是"部分克隆"或"建设者",而不是"制定者"......

如果你看java.lang.String(也是不可变的)有各种各样的方法返回一个基于旧的String(substring,toLowerCase()等)...

更新:另请参阅我喜欢的aioobe [ deriveFoo()]的答案- 它可能更清晰,特别是对于那些不熟悉Builder模式的人.


aio*_*obe 12

遵循标准API中withX(...)的样式,您可以调用它@Value.Style.

另一种选择是提供一个构建器类,它可以接受一个with="..."对象作为新对象的原型.在这种情况下,您通常将其命名x(...)为just setX(...).这会给你类似的东西

Foo newFoo = foo.withX(1047);
Run Code Online (Sandbox Code Playgroud)

  • `java.awt.Font`是JDK 1.0类,该发行版的许多命名决定都不好.JDK 8在新的`java.time` API中使用`withFoo`约定,例如[`java.time.YearMonth.withMonth()`](http://download.java.net/jdk8/docs/api/java /time/YearMonth.html#withMonth-int-). (3认同)
  • 我喜欢这种方法,+ 1 (2认同)