在一次采访中,有人问我为什么String是不可变的

我是这样回答的:

当我们在java中创建一个字符串,如string s1="hello";然后一个 对象将在字符串池(hello)中创建,s1将 指着你好。现在如果我们再次执行String s2="hello";然后 不会创建另一个对象,但s2将指向hello 因为JVM将首先检查相同的对象是否在 是否为字符串池。如果不存在,则只创建一个新的,否则不存在。

现在如果假设java允许字符串可变,那么如果我们将s1改为hello world,那么s2值也将是hello world,所以java字符串是不可变的。

谁能告诉我我的答案是对的还是错的?


当前回答

你说得对。java中的字符串使用字符串池字面量的概念。创建字符串时,如果该字符串已经存在于池中,则将返回现有字符串的引用,而不是创建一个新对象并返回其引用。如果字符串不是不可变的,用一个引用更改字符串将导致其他引用得到错误的值。

我还要补充一点,因为String是不可变的,所以对于多线程来说是安全的,单个String实例可以在不同的线程之间共享。这避免了线程安全同步的使用,字符串是隐式线程安全的。

其他回答

这可能与安全性没有多大关系,因为安全实践建议使用字符数组作为密码,而不是字符串。这是因为当不再需要数组时,可以立即删除数组。不同的是,字符串不能被擦除,因为它是不可变的。在垃圾收集之前可能需要很长时间,在内容被覆盖之前可能需要更长的时间。

我认为选择不变性是为了允许共享字符串,它们很容易分裂。字符串赋值,选择子字符串变成了一个常数时间的操作,字符串比较也是,因为可重用的哈希码是字符串数据结构的一部分,可以首先进行比较。

从另一方面来说,如果原始字符串很大(比如大型XML文档),那么从中选取少量符号可能会防止整个文档被垃圾收集。因此,后来的Java版本似乎远离了这种不变性。现代c++既有可变(std::string)版本,从c++ 17开始也有不可变(std::string_view)版本。

恕我直言,这是最重要的原因:

字符串在Java中是不可变的,因为字符串对象缓存在 字符串池。由于缓存的字符串字面值在多个字符串之间共享 客户那里总有风险,一个客户的行动就会影响到 都是另一个客户。

参考:为什么字符串是不可变或最终在Java

由于以下方面的设计、效率和安全性,Java开发人员决定字符串是不可变的。

Design Strings are created in a special memory area in java heap known as "String Intern pool". While you creating new String (Not in the case of using String() constructor or any other String functions which internally use the String() constructor for creating a new String object; String() constructor always create new string constant in the pool unless we call the method intern()) variable it searches the pool to check whether is it already exist. If it is exist, then return reference of the existing String object. If the String is not immutable, changing the String with one reference will lead to the wrong value for the other references.

根据DZone上的这篇文章:

Security String is widely used as parameter for many java classes, e.g. network connection, opening files, etc. Were String not immutable, a connection or file would be changed and lead to serious security threat. Mutable strings could cause security problem in Reflection too, as the parameters are strings. Efficiency The hashcode of string is frequently used in Java. For example, in a HashMap. Being immutable guarantees that hashcode will always the same, so that it can be cached without worrying the changes.That means, there is no need to calculate hashcode every time it is used.

你说得对。java中的字符串使用字符串池字面量的概念。创建字符串时,如果该字符串已经存在于池中,则将返回现有字符串的引用,而不是创建一个新对象并返回其引用。如果字符串不是不可变的,用一个引用更改字符串将导致其他引用得到错误的值。

我还要补充一点,因为String是不可变的,所以对于多线程来说是安全的,单个String实例可以在不同的线程之间共享。这避免了线程安全同步的使用,字符串是隐式线程安全的。

如果HELLO是你的字符串,那么你不能把HELLO改成HILLO。这个性质叫做不可变性。

你可以有多个指针字符串变量指向HELLO字符串。

但是如果HELLO是char Array,那么你可以将HELLO改为HILLO。例如,

char[] charArr = 'HELLO';
char[1] = 'I'; //you can do this

答:

编程语言具有不可变的数据变量,因此可以作为键、值对中的键使用。字符串变量用作键/索引,因此它们是不可变的。