在一次采访中,有人问我为什么String是不可变的
我是这样回答的:
当我们在java中创建一个字符串,如string s1="hello";然后一个
对象将在字符串池(hello)中创建,s1将
指着你好。现在如果我们再次执行String s2="hello";然后
不会创建另一个对象,但s2将指向hello
因为JVM将首先检查相同的对象是否在
是否为字符串池。如果不存在,则只创建一个新的,否则不存在。
现在如果假设java允许字符串可变,那么如果我们将s1改为hello world,那么s2值也将是hello world,所以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.
字符串是不可变的有几个原因,这里是一个总结:
Security: parameters are typically represented as String in network connections, database connection urls, usernames/passwords etc. If it were mutable, these parameters could be easily changed.
Synchronization and concurrency: making String immutable automatically makes them thread safe thereby solving the synchronization issues.
Caching: when compiler optimizes your String objects, it sees that if two objects have same value (a="test", and b="test") and thus you need only one string object (for both a and b, these two will point to the same object).
Class loading: String is used as arguments for class loading. If mutable, it could result in wrong class being loaded (because mutable objects change their state).
也就是说,String的不可变性只是意味着你不能使用它的公共API改变它。实际上,您可以使用反射绕过常规API。在这里看到答案。
在你的例子中,如果String是可变的,那么考虑下面的例子:
String a="stack";
System.out.println(a);//prints stack
a.setValue("overflow");
System.out.println(a);//if mutable it would print overflow