不可变到底是什么意思——也就是说,对象可变或不可变的结果是什么?特别是,为什么Java的字符串是不可变的?

我的理解是StringBuilder类型类似于String的可变等价。什么时候我会使用StringBuilder而不是字符串,反之亦然?


当前回答

java.time

这可能有点晚了,但为了理解什么是不可变对象,请考虑以下来自新的Java 8日期和时间API (Java . Time)的示例。你可能知道,Java 8中的所有日期对象都是不可变的,所以在下面的例子中

LocalDate date = LocalDate.of(2014, 3, 18); 
date.plusYears(2);
System.out.println(date);

输出:

2014-03-18

这将打印与初始日期相同的年份,因为plusYears(2)返回一个新对象,因此旧日期仍然不变,因为它是一个不可变对象。一旦创建,您就不能进一步修改它,日期变量仍然指向它。

因此,该代码示例应该捕获并使用由plusYears调用实例化并返回的新对象。

LocalDate date = LocalDate.of(2014, 3, 18); 
LocalDate dateAfterTwoYears = date.plusYears(2);

date.toString()…2014-03-18 dateAfterTwoYears.toString()…2016-03-18

其他回答

一旦实例化,就不能更改。考虑一个类,它的实例可能用作哈希表或类似的键。查看Java最佳实践。

不可变意味着一旦对象被创建,它的所有成员都不会改变。字符串是不可变的,因为你不能改变它的内容。 例如:

String s1 = "  abc  ";
String s2 = s1.trim();

在上面的代码中,字符串s1没有改变,使用s1创建了另一个对象(s2)。

“不可变”意味着你不能改变值。如果你有一个String类的实例,你调用的任何方法,只要看起来是在修改这个值,实际上都会创建另一个String。

String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"

要保存更改,您应该这样做 Foo = Foo .sustring(3);

当您使用集合时,不可变与可变可能会很有趣。想想如果使用可变对象作为map的键,然后更改值会发生什么(提示:考虑equals和hashCode)。

不可变对象

一个对象被认为是不可变的,如果它的状态在被构造后不能改变。对于创建简单、可靠的代码,最大程度地依赖于不可变对象是一种被广泛接受的合理策略。

不可变对象在并发应用程序中特别有用。由于它们不能改变状态,因此不会被线程干扰破坏或在不一致的状态下观察到。

程序员通常不愿意使用不可变对象,因为他们担心创建新对象的成本,而不是在适当的地方更新对象。对象创建的影响经常被高估,并且可以被一些与不可变对象相关的效率所抵消。这包括减少垃圾收集带来的开销,以及消除保护可变对象不受损坏所需的代码。

下面的子节采用一个实例是可变的类,并从中派生一个具有不可变实例的类。在这样做的过程中,他们给出了这种转换的一般规则,并演示了不可变对象的一些优点。

其中一个含义与值如何存储在计算机中有关,例如,对于一个。net字符串,它意味着内存中的字符串不能被更改,当你认为你正在更改它时,你实际上是在内存中创建了一个新的字符串,并将现有的变量(这只是一个指向其他地方的实际字符集合的指针)指向新的字符串。