让我们分成几个部分
String s1 = "hello";
该语句创建包含问候的字符串,并在内存(即常量字符串池)中占用空间,并将其分配给引用对象s1
String s2 = s1;
该语句将相同的字符串hello分配给新引用s2
__________
| |
s1 ---->| hello |<----- s2
|__________|
两个引用都指向相同的字符串,因此输出相同的值,如下所示。
out.println(s1); // o/p: hello
out.println(s2); // o/p: hello
尽管String是不可变的,但赋值是可能的,因此s1现在将引用新值堆栈。
s1 = "stack";
__________
| |
s1 ---->| stack |
|__________|
但是,指向hello的s2对象将保持原样。
__________
| |
s2 ---->| hello |
|__________|
out.println(s1); // o/p: stack
out.println(s2); // o/p: hello
由于String是不可变的,因此Java虚拟机不允许我们通过其方法修改字符串s1。它将在池中创建所有新的String对象,如下所示。
s1.concat(" overflow");
___________________
| |
s1.concat ----> | stack overflow |
|___________________|
out.println(s1); // o/p: stack
out.println(s2); // o/p: hello
out.println(s1.concat); // o/p: stack overflow
注意,如果String是可变的,那么输出将是
out.println(s1); // o/p: stack overflow
现在您可能会惊讶,为什么String 会修改诸如concat()之类的方法。遵循以下摘要将清除您的困惑。
s1 = s1.concat(" overflow");
在这里,我们将修改后的字符串值分配回s1参考。
___________________
| |
s1 ---->| stack overflow |
|___________________|
out.println(s1); // o/p: stack overflow
out.println(s2); // o/p: hello
这就是Java决定String为最终类的原因,否则任何人都可以修改和更改string的值。希望这会有所帮助。