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

我是这样回答的:

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

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

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


当前回答

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

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

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

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

答:

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

其他回答

根据DZone的这篇文章,最重要的原因是:

字符串常量池 ... 如果字符串是可变的,用一个引用更改字符串将导致其他引用得到错误的值。 安全 字符串被广泛用作许多java类的参数,例如网络连接,打开文件等。如果字符串不是不可变的,则连接或文件将被更改,从而导致严重的安全威胁。 ...

希望对你有所帮助。

字符串是不可变的有几个原因,这里是一个总结:

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

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

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

从安全的角度来看,我们可以使用这个实际的例子:

DBCursor makeConnection(String IP,String PORT,String USER,String PASS,String TABLE) {

    // if strings were mutable IP,PORT,USER,PASS can be changed by validate function
    Boolean validated = validate(IP,PORT,USER,PASS);

    // here we are not sure if IP, PORT, USER, PASS changed or not ??
    if (validated) {
         DBConnection conn = doConnection(IP,PORT,USER,PASS);
    }

    // rest of the code goes here ....
}

字符串是不可变的Sun微系统,因为字符串可以用来存储在地图集合的关键。 StringBuffer是可变的,这就是它不能在map对象中用作键的原因