4

在一次采访中,有人问我“字符串是如何变得不可变的?” 由于我不确定答案,所以我没有回复。我后来问了面试官同样的问题。答案是 String 类是最终的,这就是实现不变性的方式。

这是正确的答案吗?如果是,即使 StringBuffer 也被标记为最终类。那么为什么 StringBuffer 不是不可变的呢?

4

7 回答 7

11

它是以下各项的组合:

  1. 字段是私有的 - 因此您不能直接更改它们。
  2. 没有提供任何set方法 - 所以它们也不能间接改变。
  3. Stringfinal- 所以你不能向它添加可变性(即设置器等)。
于 2013-02-11T13:51:42.580 回答
4

不,这不是正确的答案。String 实现了不变性,因为它没有为您提供任何更改其内部内容的方法。因此,您可以实例化一个 String 对象,为其分配一个引用,但一旦初始化就不能更改其内容。

于 2013-02-11T13:52:09.163 回答
3

字符串是不可变对象。

按照以下准则使类不可变:

  • 确保类不能被覆盖
  • 制作类final,或使用静态工厂并使构造函数保持私有
  • 制作字段privatefinal
  • 不提供任何可以以任何方式改变对象状态的方法——不仅仅是setXXX方法,还有任何可以改变状态的方法,如果类有任何可变对象字段,那么当在类和它的类之间传递时,它们必须被防御性地复制呼叫者
  • 强制调用者在一个步骤中完全构造一个对象,而不是使用无参数构造函数和对setXXX方法的后续调用(即避免 Java Beans 约定)
于 2013-02-11T13:59:14.563 回答
2

关键字与final不变性不同。String是不可变的,因为它没有定义任何允许用户更改其内容的方法,并且它是最终的,消除了在子类中更改事物的可能性。

制作像List实例变量 final 之类的东西仍然允许您更改其内容,使其可变。

于 2013-02-11T13:53:20.030 回答
1

作为 final 意味着它不能被派生出来。这并不赋予不变性

不变性是通过封装实现的,并且不提供任何方法来修改内部保存的字符数组。即不存在修改内部字段的方法。

于 2013-02-11T13:54:32.323 回答
0

一个字符串池,最初是空的,由 String 类私下维护。

您应该查看 String 的 JavaDoc: public native String intern();

看:

于 2013-02-11T13:54:28.707 回答
0

使类不可变的常用方法是确保:

  • 所有字段都是私有的;
  • 构建后无法修改字段;
  • 它是最终的(因此扩展不能破坏不变性)。

String 有点特殊,至少在 Sun/Oracle 实现中,它实际上并没有遵循这个过程。该实现有一个可变字段,它在其中缓存对象的哈希码。因此,虽然有一种方法可以改变对象的内部状态(hashCode),但这种状态改变不会以任何方式改变对象的行为。任何后续调用都hashCode将运行得更快,但结果不会有任何不同。

于 2013-02-11T14:21:11.213 回答