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

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


当前回答

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

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

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

其他回答

我真的很喜欢SCJP Sun认证程序员Java 5学习指南的解释。

为了提高Java的内存效率,JVM留出了一个特殊的内存区域,称为“字符串常量池”。当编译器遇到String字面值时,它会检查池,看看是否已经存在相同的String。如果找到匹配,则对新字面值的引用将指向现有的String,并且不会创建新的String字面值对象。

因为公认的答案不能回答所有的问题。11年零6个月后,我不得不给出答案。

有人能解释一下什么是不可变吗?

希望你指的是不可变对象(因为我们可以考虑不可变引用)。

对象是不可变的:iff一旦创建,它们总是表示相同的值(没有任何改变值的方法)。

为什么字符串是不可变的?

尊重上面的定义,这可以通过查看Sting.java源代码来检查。

不可变对象的优点/缺点是什么? 不可变类型有:

更安全,远离虫子。 更容易理解。 而且更愿意改变。

为什么像StringBuilder这样的可变对象应该优先于String,反之亦然?

缩小问题为什么我们在编程中需要可变的StringBuilder ? 它的一个常见用途是将大量字符串连接在一起,就像这样:

String s = "";
for (int i = 0; i < n; ++i) {
    s = s + n;
}

使用不可变字符串,这会产生大量临时拷贝——在构建最终字符串的过程中,字符串的第一个数字(“0”)实际上被复制n次,第二个数字被复制n-1次,依此类推。实际上,做所有这些复制需要花费O(n2)时间,尽管我们只连接了n个元素。

StringBuilder的设计目的是最小化这种复制。它使用了一个简单但巧妙的内部数据结构来避免任何复制,直到最后,当你使用toString()调用来请求最终的String时:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; ++i) {
  sb.append(String.valueOf(n));
}
String s = sb.toString();

获得良好的性能是我们使用可变对象的原因之一。另一个是方便的共享:通过共享一个公共的可变数据结构,程序的两个部分可以更方便地通信。

更多信息请访问:https://web.mit.edu/6.005/www/fa15/classes/09-immutability/#useful_immutable_types

不可变的对象在创建后不能改变其状态。

尽可能使用不可变对象有三个主要原因,所有这些都将有助于减少你在代码中引入的错误数量:

It is much easier to reason about how your program works when you know that an object's state cannot be changed by another method Immutable objects are automatically thread safe (assuming they are published safely) so will never be the cause of those hard-to-pin-down multithreading bugs Immutable objects will always have the same Hash code, so they can be used as the keys in a HashMap (or similar). If the hash code of an element in a hash table was to change, the table entry would then effectively be lost, since attempts to find it in the table would end up looking in the wrong place. This is the main reason that String objects are immutable - they are frequently used as HashMap keys.

当你知道一个对象的状态是不可变的时,你还可以在代码中做一些其他的优化——例如缓存计算的哈希——但这些都是优化,因此没有那么有趣。

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

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

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

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