简体   繁体   English

了解Java中的字符串不变性

[英]Understanding String Immutability in Java

While trying the understand the reasons behind why strings are immutable, I wrote a simple program as follows: 在尝试理解字符串不可变背后的原因时,我编写了一个简单的程序,如下所示:

/* Program to test string immutability */

public class StringImmutability
{
    public static void main(String args[])
    {
        String s = "hello";
        s.concat(" world"); // returns a new string object. So, the reference must point to this object for further processing like this: s = s.concat(" world");
        System.out.println(s);
        s = s.concat(" world");
        System.out.println(s);
        String s1 = s, s2 = s, s3 = s;
        System.out.println(s1+" "+s2+" "+s3);
        s = s.concat(" test");
        //The references are modified
        System.out.println(s1+" "+s2+" "+s3); 
    }
}

The output though isn't as expected: 虽然输出不符合预期:

hello
hello world
hello world hello world hello world
hello world hello world hello world

After the references are modified, the output must be hello world test repeated thrice but there isn't any change in output. 修改引用后,输出必须重复三次hello world test但输出没有任何变化。

It is working exactly as expected. 它的工作完全符合预期。 Let's look at it step by step: 让我们一步一步看一下:

String s = "hello";
s.concat(" world");

在此处输入图片说明

This is effectively a NOP because you are not assigning the result of concat to anything. 这实际上是NOP,因为您没有将concat的结果分配给任何东西。 That new String instance is lost to the ether and garbage collected since there is nothing referring to it. 该新的String实例将丢失给以太并收集垃圾,因为没有任何引用。 Hence, your s remains unchanged. 因此,您s保持不变。

s = s.concat(" world");

在此处输入图片说明

Here s.concat(" world") returns a new String instance, and you have reassigned s to that. 在这里s.concat(" world")返回一个新的String实例,并且您已将s重新分配给它。 So s now points to this new string and you have lost the reference to the older one (the one that just had hello in it). 所以s现在指向这个字符串,并且您已经失去了对旧字符串(刚刚在其中hello字符串)的引用。

String s1 = s, s2 = s, s3 = s;

在此处输入图片说明

Here you have created three variables that all point to the same string instance that s points to. 在这里,您创建了三个变量,它们全部指向s指向的同一字符串实例。

s = s.concat(" test");

在此处输入图片说明

This is a repeat of what you did earlier. 这是您之前所做的重复。 concat creates a new string instance and you reassign s to that. concat创建一个新字符串实例,并重新分配s了这一点。 But keep in mind that s1 , s2 , and s3 are still pointing to what s used to point to and so they will not reflect the changes. 但是请记住, s1s2s3仍指向s 指向的内容,因此它们不会反映更改。

You've only stopped s from pointing to the old string and made it point to the new one. 您仅使s不再指向旧字符串,而是使其指向新字符串。 But your other variables are still pointing to that old string. 但是您的其他变量仍指向该旧字符串。

Your code proves String immutability. 您的代码证明了字符串的不变性。 You can change the String that a variable refers to, but you can't change the String object itself (other than through shifty reflection tricks that I won't discuss here). 您可以更改变量所引用的String,但不能更改String对象本身(除非通过在这里不讨论的易变的反射技巧)。 The error above is in your expected output and nothing else. 上面的错误在您的预期输出中,仅此而已。 For example, 例如,

s = s.concat(" test"); 

creates a new String object and assigns it to the s variable. 创建一个新的 String对象并将其分配给s变量。 It does not and cannot change the original object that s referred to. 它没有也不会改变原来的对象s简称。

s is reassigned to a new string that has the " test" String appended to the end of the target String value ( s pre-assignment). s被重新分配给一个新字符串,该String的目标String值( s预先分配)的末尾附加了" test" String

s = s.concat(" test");

This does not affect the String value stored in s1 , s2 , or s3 , since concat returns a new String object. 这不会影响存储在s1s2s3String值,因为concat返回一个新的String对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM