Java中字符串的不变性
考虑以下示例。
String str = new String();str = "Hello";
System.out.println(str); //Prints Hello
str = "Help!";
System.out.println(str); //Prints Help!
现在,在Java中,String对象是不可变的。然后如何为对象str
分配值“帮助!”。这是否与Java中字符串的不变性相矛盾?有人可以向我解释不变性的确切概念吗?
编辑:
好。我现在明白了,但只是一个后续问题。那么下面的代码呢:
String str = "Mississippi"; System.out.println(str); // prints Mississippi
str = str.replace("i", "!");
System.out.println(str); // prints M!ss!ss!pp!
这是否意味着将再次创建两个对象(“密西西比”和“ M!ss!ss!pp!”),并且引用str
在replace()
方法之后指向另一个对象?
回答:
str
不是对象,而是对对象的引用。"Hello"
和"Help!"
是两个不同的String
对象。因此,str
指向一个字符串。你可以更改其指向的内容,但不能更改其指向的内容。
以下面的代码为例:
String s1 = "Hello";String s2 = s1;
// s1 and s2 now point at the same string - "Hello"
现在,没有什么1
,我们可以做些什么来s1会影响价值s2
。它们引用同一个对象-字符串"Hello"
-但该对象是不可变的,因此无法更改。
如果我们做这样的事情:
s1 = "Help!";System.out.println(s2); // still prints "Hello"
在这里,我们看到了改变对象和更改参考之间的区别。s2
仍然指向与最初设置的对象相同的对象s1
。设置s1
为"Help!"
仅更改引用,而String
最初引用的对象保持不变。
如果字符串是可变的,我们可以这样做:
String s1 = "Hello";String s2 = s1;
s1.setCharAt(1, 'a'); // Fictional method that sets character at a given pos in string
System.out.println(s2); // Prints "Hallo"
如果你查看String.replace(char,char)
的源代码(也可以在JDK安装目录的src.zip中找到它-一个专业技巧是在你想知道某事真正起作用时去那里查看),你会看到它确实是以下内容:
- 如果
oldChar
当前字符串中有一个或多个出现,请复制当前字符串的副本,其中所有出现的oldChar都替换为newChar
。 - 如果
oldChar
当前字符串中不存在,则返回当前字符串。是的,
"Mississippi".replace('i', '!')
创建一个新String
对象。同样,以下内容成立:
String s1 = "Mississippi";String s2 = s1;
s1 = s1.replace('i', '!');
System.out.println(s1); // Prints "M!ss!ss!pp!"
System.out.println(s2); // Prints "Mississippi"
System.out.println(s1 == s2); // Prints "false" as s1 and s2 are two different objects
现在,你的作业是查看上面的代码在更改s1 = s1.replace('i', '!')
;为s1 = s1.replace('Q', '!')
;时的作用。
1实际上,它是可能的突变的字符串(和其他不可变的对象)。它需要反射,非常非常危险,除非你真的有兴趣破坏程序,否则永远不要使用它。
以上是 Java中字符串的不变性 的全部内容, 来源链接: utcz.com/qa/403879.html