字符串是不可变的。请参阅此代码。
String a="ninja";
String b= "ninja";
String c=a+" name ";
在这个图中,a和b指向同一个对象。c将是另一个对象。当两个字符串指向同一个对象时,它将如何变为不可变的?假设我用另一个字符串修改,a="忍者龟"
然后它将指向堆中的另一个位置。那么,有人能详细解释一下吗,当我们可以修改这个对象时,你怎么能说它是不可变的呢?
String
是不可变的,您不能更改它。分配a = "ninjaturtle"
只会使a
指向另一个字符串,而不会更改b
指向的字符串。
您混淆了两件事1) 引用变量——它类似于指针(不是真的,你不能真的做指针操作)2) 对象——引用指向的变量的实际对象
字符串对象是一种一旦创建就永远不能更改值的对象类型。这就是为什么它是不可变的。相反,若您正在考虑StringBuilder对象,则可以更改其值。因此它是一个可变的对象。
举个例子:
字符串a="ninja";
a) 当遇到上面的语句时,JVM会查看字符串池中是否已经存在值为"ninja"的字符串对象,如果没有,则会创建一个新的字符串对象并将其存储在字符串池中。
请注意:此处的"a"是指向值为"ninja"的字符串对象的指针
String b="忍者";
b) 当再次遇到此语句时,JVM将遵循与上面相同的过程,从而查看字符串池中是否已经存在值为"ninja"的对象。正如我们所知,我们已经在步骤a)中创建了这样一个对象。现在,编译器不会创建一个新对象,但它会将"b"指向值为"ninja"的同一对象
字符串c=a+"名称";
c) 该语句再次遵循上面提到的相同过程,并创建一个值为"忍者名称"的新对象
在以上三条语句之后,我们在字符串池中有以下语句:
a------------------------>新字符串("ninja");
b-------------------------------^
c------------------------->新字符串("忍者名称");
要给出您的答案,请尝试修改"a"。
a="忍者名称";
d) 现在,编译器将首先检查字符串池,因为值为"ninja name"的对象已经存在,指针"a"现在将指向新的字符串("ninja name")"
因此,字符串池现在有以下字符串池:
b------------------------->新字符串("ninja");
c------------------------->新字符串("忍者名称");
a-------------------------------^
如果您注意到字符串池中的字符串对象仍然相同。当我们试图修改它们时,它们只指向池中的其他字符串对象,或者创建了一个新的字符串,但现有的字符串从未被修改这是字符串的不变性
不可变意味着不能更改物理字符串。这意味着,虽然我可以更改字符串指向的位置,但我不能以任何方式更改字符串。
这就是为什么当你做这样的事情时
String a = " hello world";
a.trim();
System.out.println(a); //Prints out: hello world
在"你好世界"之前还有4个空格。
你必须重新分配位置,就像这样:
String a = " hello world";
a = a.trim();
System.out.println(a); //Prints out:hello world
字符串不变,内存位置不变。