不可变到底是什么意思——也就是说,对象可变或不可变的结果是什么?特别是,为什么Java的字符串是不可变的?
我的理解是StringBuilder类型类似于String的可变等价。什么时候我会使用StringBuilder而不是字符串,反之亦然?
不可变到底是什么意思——也就是说,对象可变或不可变的结果是什么?特别是,为什么Java的字符串是不可变的?
我的理解是StringBuilder类型类似于String的可变等价。什么时候我会使用StringBuilder而不是字符串,反之亦然?
当前回答
不可改变的意思是不可改变的。字符串对象一旦创建,其数据或状态就不能更改
考虑下面的例子:
class Testimmutablestring{
public static void main(String args[]){
String s="Future";
s.concat(" World");//concat() method appends the string at the end
System.out.println(s);//will print Future because strings are immutable objects
}
}
让我们考虑一下波纹图,
在这个图中,你可以看到一个新对象被创建为“Future World”。但不改变“未来”。因为字符串是不可变的。s,仍指“未来”。如果你需要给“未来世界”打电话,
String s="Future";
s=s.concat(" World");
System.out.println(s);//print Future World
为什么在java中字符串对象是不可变的?
因为Java使用了字符串字面量的概念。假设有5个引用变量,都指向一个对象“Future”。如果一个引用变量改变了对象的值,它将影响到所有的引用变量。这就是为什么字符串对象在java中是不可变的。
其他回答
不可变的对象在创建后不能改变其状态。
尽可能使用不可变对象有三个主要原因,所有这些都将有助于减少你在代码中引入的错误数量:
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.
当你知道一个对象的状态是不可变的时,你还可以在代码中做一些其他的优化——例如缓存计算的哈希——但这些都是优化,因此没有那么有趣。
我真的很喜欢SCJP Sun认证程序员Java 5学习指南的解释。
为了提高Java的内存效率,JVM留出了一个特殊的内存区域,称为“字符串常量池”。当编译器遇到String字面值时,它会检查池,看看是否已经存在相同的String。如果找到匹配,则对新字面值的引用将指向现有的String,并且不会创建新的String字面值对象。
不可变意味着一旦一个对象的构造函数完成执行,该实例就不能被改变。
这很有用,因为这意味着你可以传递对对象的引用,而不用担心其他人会改变它的内容。特别是在处理并发性时,对于永不更改的对象不存在锁定问题
e.g.
class Foo
{
private final String myvar;
public Foo(final String initialValue)
{
this.myvar = initialValue;
}
public String getValue()
{
return this.myvar;
}
}
Foo不必担心getValue()的调用者可能会更改字符串中的文本。
如果你想象一个类似于Foo的类,但是成员是StringBuilder而不是String,你可以看到getValue()的调用者能够改变Foo实例的StringBuilder属性。
还要注意你可能会发现的不同类型的不变性:Eric Lippert写了一篇关于这个的博客文章。基本上,你可以拥有接口是不可变的对象,但在幕后实际可变的私有状态(因此不能在线程之间安全地共享)。
其中一个含义与值如何存储在计算机中有关,例如,对于一个。net字符串,它意味着内存中的字符串不能被更改,当你认为你正在更改它时,你实际上是在内存中创建了一个新的字符串,并将现有的变量(这只是一个指向其他地方的实际字符集合的指针)指向新的字符串。
不可变对象是指创建后不能修改的对象。一个典型的例子是字符串字面量。
越来越流行的D编程语言通过“不变”关键字具有“不变性”的概念。查看Dr.Dobb关于它的文章http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29。它完美地解释了这个问题。