用Java创建不可变对象

时间:2013-05-20 23:15:04

标签: java design-patterns immutability

我想为我的代码库创建一些不可变对象。真正传递给定类是不可变的消息的最佳方法是什么?我应该将所有字段都设为最终字段,并在对象构建期间进行初始化吗? (这看起来真的很尴尬......)我应该创建一些不可变的接口,并让对象实现它吗? (由于Java背后没有一些标准接口,我认为他们还有其他一些处理它的方法。)处理这个问题的标准方法是什么? (如果简单地通过在字段周围添加一堆注释来表示它们一旦初始化就不应该被修改,那也没关系。)

3 个答案:

答案 0 :(得分:8)

  

我是否应该将所有字段设为最终字段,并在对象构建期间进行初始化?

是。并确保这些类型本身是不可变的,或者在从getter方法返回值时创建副本。并使课程本身最终。 (否则你的类本身可能是不可变的,但这并不意味着你的类的任何实例都是不可变的 - 因为它可能是一个可变子类的实例。)

  

(这看起来真的很尴尬......)

如果不知道如何你觉得它很尴尬,很难知道建议什么 - 但是构建器模式通常很有用。我通常使用嵌套的静态类,通常使用静态工厂方法。所以你最终得到:

Foo foo = Foo.newBuilder()
    .setName("asd")
    .setPoints(10)
    .setOtherThings("whatever")
    .build();

答案 1 :(得分:5)

是和否。使所有领域成为最终并不是本身的保证。如果您想深入了解这一点,Joshua Bloch撰写的有效Java中有许多章节涉及不变性和涉及的考虑因素。 Effective Java中的第15项涵盖了大部分内容,并引用了其他相关项目。

他提供了以下五个步骤:

  1. 不提供任何修改对象状态的方法(称为muta- 职责范围)。

  2. 确保无法扩展该类。

  3. 将所有字段设为最终字段。

  4. 将所有字段设为私有。

  5. 确保对任何可变组件的独占访问权限。

  6. 学习如何完成所有这些操作的一种方法是通过查看不可变的String类(例如,参见http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java)来查看语言设计者如何使类不可变。

答案 2 :(得分:1)

编写一个单元测试,如果你的同事让这个类变异,那将会失败。

使用Mutability Detector,您可以编写如下测试:

import static org.mutabilitydetector.unittesting.MutabilityAssert.assertImmutable;

@Test public void isImmutable() {
    assertImmutable(MyImmutableThing.class)
}

如果同事出现,并且例如在您的班级中添加了一个setter方法,则测试将失败。您的用例是Mutability Detector的核心目的之一。

免责声明:我写了它。

相关问题