小编典典

Java中字符串的不变性

all

考虑以下示例。

String str = new String();

str  = "Hello";
System.out.println(str);  //Prints Hello

str = "Help!";
System.out.println(str);  //Prints Help!

现在,在 Java 中,String 对象是不可变的。那么为什么可以为对象str分配值“Help!”。这不是与 Java
中字符串的不变性相矛盾吗?谁能解释一下不变性的确切概念?

编辑:

好的。我现在明白了,但只是一个后续问题。下面的代码呢:

String str = "Mississippi"; 
System.out.println(str); // prints Mississippi

str = str.replace("i", "!"); 
System.out.println(str); // prints M!ss!ss!pp!

这是否意味着再次创建了两个对象(“Mississippi”和“M!ss!ss!pp!”),并且引用在方法str之后指向不同的对象replace()


阅读 57

收藏
2022-06-07

共1个答案

小编典典

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"

编辑以响应 OP 的编辑:

如果您查看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实际上, 可以 改变字符串(和其他不可变对象)。它需要反射,非常非常危险,除非你真的有兴趣破坏程序,否则永远不应该使用它。

2022-06-07