用Java创建不可变对象

Sal*_*Sal 3 java design-patterns immutability

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

Jon*_*eet 8

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

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

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

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

Foo foo = Foo.newBuilder()
    .setName("asd")
    .setPoints(10)
    .setOtherThings("whatever")
    .build();
Run Code Online (Sandbox Code Playgroud)

  • 为'确保这些类型本身是不可变的'.您对Immutable接口或注释作为类似于Serializable接口的元数据的看法是什么? (2认同)
  • 如果你没有setter,你不必将它们作为最终版本,但这样做可以清楚地向读者表明你的代码意图是什么,这是良好编程的核心.此外,字段不必是不可变的 - 如果不是,则让getter返回副本. (2认同)

Sco*_*ipp 5

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

他提供以下五个步骤:

  1. 不要提供任何修改对象状态的方法(称为变体).

  2. 确保无法扩展该类.

  3. 让所有领域最终.

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

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

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