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


当前回答

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

其他回答

不可变性与安全性并没有那么紧密的联系。为此,至少在。net中,你得到了SecureString类。

稍后编辑:在Java中,你会发现GuardedString,一个类似的实现。

在大多数情况下,“字符串”(被用作/视为/认为/假定)是一个有意义的原子单位,就像一个数字一样。

因此,问为什么字符串的单个字符是不可变的,就像问为什么整数的单个比特是不可变的一样。

你应该知道原因。想想看。

我不想这么说,但不幸的是,我们正在讨论这个问题,因为我们的语言很糟糕,我们试图使用一个单一的词,字符串,来描述一个复杂的,上下文定位的概念或对象类。

我们对“字符串”执行计算和比较,类似于对数字的操作。如果字符串(或整数)是可变的,我们必须编写特殊的代码来将它们的值锁定为不可变的局部形式,以便可靠地执行任何类型的计算。因此,最好将字符串视为数字标识符,但它可能是数百位,而不是16位、32位或64位。

When someone says "string", we all think of different things. Those who think of it simply as a set of characters, with no particular purpose in mind, will of course be appalled that someone just decided that they should not be able to manipulate those characters. But the "string" class isn't just an array of characters. It's a STRING, not a char[]. There are some basic assumptions about the concept we refer to as a "string", and it generally can be described as meaningful, atomic unit of coded data like a number. When people talk about "manipulating strings", perhaps they're really talking about manipulating characters to build strings, and a StringBuilder is great for that. Just think a bit about what the word "string" truly means.

考虑一下如果字符串是可变的会是什么样子。如果可变用户名字符串在此函数使用时被另一个线程有意或无意地修改,则以下API函数可能被欺骗返回不同用户的信息:

string GetPersonalInfo( string username, string password )
{
    string stored_password = DBQuery.GetPasswordFor( username );
    if (password == stored_password)
    {
        //another thread modifies the mutable 'username' string
        return DBQuery.GetPersonalInfoFor( username );
    }
}

安全不仅仅是“访问控制”,它还涉及“安全性”和“保证正确性”。如果一个方法不容易编写,也不能可靠地依靠它来执行简单的计算或比较,那么调用它是不安全的,但是对编程语言本身提出质疑是安全的。

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

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

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

至少有两个原因。

第一-安全http://www.javafaq.nu/java-article1060.html

The main reason why String made immutable was security. Look at this example: We have a file open method with login check. We pass a String to this method to process authentication which is necessary before the call will be passed to OS. If String was mutable it was possible somehow to modify its content after the authentication check before OS gets request from program then it is possible to request any file. So if you have a right to open text file in user directory but then on the fly when somehow you manage to change the file name you can request to open "passwd" file or any other. Then a file can be modified and it will be possible to login directly to OS.

第二-内存效率http://hikrish.blogspot.com/2006/07/why-string-class-is-immutable.html

JVM internally maintains the "String Pool". To achive the memory efficiency, JVM will refer the String object from pool. It will not create the new String objects. So, whenever you create a new string literal, JVM will check in the pool whether it already exists or not. If already present in the pool, just give the reference to the same object or create the new object in the pool. There will be many references point to the same String objects, if someone changes the value, it will affect all the references. So, sun decided to make it immutable.