为什么他们决定在Java和。net(和其他一些语言)中使字符串不可变?为什么不让它变呢?


当前回答

这是一种权衡。字符串进入String池,当您创建多个相同的字符串时,它们共享相同的内存。设计人员认为这种节省内存的技术在一般情况下会很好地工作,因为程序倾向于反复处理相同的字符串。

缺点是连接产生了许多额外的字符串,这些字符串只是过渡性的,只是垃圾,实际上会损害内存性能。在这些情况下,可以使用StringBuffer和StringBuilder(在Java中,。net中也有StringBuilder)来保存内存。

其他回答

人们应该问,“为什么X应该是可变的?”最好默认为不可变,因为Princess Fluff已经提到了它的好处。它应该是一个例外,某些东西是可变的。

不幸的是,目前大多数编程语言都默认为可变性,但希望未来的默认更多地是不变性(参见下一个主流编程语言的愿望清单)。

这是一种权衡。字符串进入String池,当您创建多个相同的字符串时,它们共享相同的内存。设计人员认为这种节省内存的技术在一般情况下会很好地工作,因为程序倾向于反复处理相同的字符串。

缺点是连接产生了许多额外的字符串,这些字符串只是过渡性的,只是垃圾,实际上会损害内存性能。在这些情况下,可以使用StringBuffer和StringBuilder(在Java中,。net中也有StringBuilder)来保存内存。

一个因素是,如果字符串是可变的,那么存储字符串的对象必须小心地存储副本,以免它们的内部数据在没有通知的情况下发生变化。鉴于字符串是一种相当基本的类型,就像数字一样,即使它们是通过引用传递的,也可以把它们当作是按值传递的,这是很好的(这也有助于节省内存)。

我知道这是个意外,但是… 它们真的是不可变的吗? 考虑以下几点。

public static unsafe void MutableReplaceIndex(string s, char c, int i)
{
    fixed (char* ptr = s)
    {
        *((char*)(ptr + i)) = c;
    }
}

...

string s = "abc";
MutableReplaceIndex(s, '1', 0);
MutableReplaceIndex(s, '2', 1);
MutableReplaceIndex(s, '3', 2);
Console.WriteLine(s); // Prints 1 2 3

你甚至可以让它成为一个扩展方法。

public static class Extensions
{
    public static unsafe void MutableReplaceIndex(this string s, char c, int i)
    {
        fixed (char* ptr = s)
        {
            *((char*)(ptr + i)) = c;
        }
    }
}

是什么使下面的工作

s.MutableReplaceIndex('1', 0);
s.MutableReplaceIndex('2', 1);
s.MutableReplaceIndex('3', 2);

Conclusion: They're in an immutable state which is known by the compiler. Of couse the above only applies to .NET strings as Java doesn't have pointers. However a string can be entirely mutable using pointers in C#. It's not how pointers are intended to be used, has practical usage or is safely used; it's however possible, thus bending the whole "mutable" rule. You can normally not modify an index directly of a string and this is the only way. There is a way that this could be prevented by disallowing pointer instances of strings or making a copy when a string is pointed to, but neither is done, which makes strings in C# not entirely immutable.

String不是一个基本类型,但你通常想用值语义来使用它,即像一个值。

价值观是你可以信任的东西,不会在你背后改变。 String str = someExpr(); 你不希望它改变,除非你对str做些什么。

String作为对象自然具有指针语义,为了获得值语义,它也需要是不可变的。