Java中字符串的不变性 [英] Immutability of Strings in Java
问题描述
考虑以下示例.
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 中字符串的不变性相矛盾吗?有人能解释一下不变性的确切概念吗?
Now, in Java, String objects are immutable. Then how come the object str
can be assigned value "Help!". Isn't this contradicting the immutability of strings in Java? Can anybody please explain me the exact concept of immutability?
好的.我现在明白了,但只是一个后续问题.下面的代码怎么样:
Ok. I am now getting it, but just one follow-up question. What about the following code:
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()
方法?
Does this mean that two objects are created again ("Mississippi" and "M!ss!ss!pp!") and the reference str
points to a different object after replace()
method?
推荐答案
str
不是对象,而是对对象的引用."Hello"
和 "Help!"
是两个不同的 String
对象.因此,str
指向一个字符串.你可以改变它指向的东西,但不能改变它指向的东西.
str
is not an object, it's a reference to an object. "Hello"
and "Help!"
are two distinct String
objects. Thus, str
points to a string. You can change what it points to, but not that which it points at.
以这段代码为例:
String s1 = "Hello";
String s2 = s1;
// s1 and s2 now point at the same string - "Hello"
现在,我们可以对 s1
做任何事情1来影响 s2
的值.它们引用同一个对象 - 字符串 "Hello"
- 但该对象是不可变的,因此无法更改.
Now, there is nothing1 we could do to s1
that would affect the value of s2
. They refer to the same object - the string "Hello"
- but that object is immutable and thus cannot be altered.
如果我们这样做:
s1 = "Help!";
System.out.println(s2); // still prints "Hello"
在这里我们看到了改变对象和改变引用之间的区别.s2
仍然指向与我们最初设置 s1
指向的相同的对象.将 s1
设置为 "Help!"
只会改变 reference,而它最初引用的 String
对象保持不变.
Here we see the difference between mutating an object, and changing a reference. s2
still points to the same object as we initially set s1
to point to. Setting s1
to "Help!"
only changes the reference, while the String
object it originally referred to remains unchanged.
如果字符串是可变的,我们可以这样做:
If strings were mutable, we could do something like this:
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 的
如果您查看字符串的源代码.replace(char,char)(也可以在 JDK 安装目录中的 src.zip 中找到——一个专业提示是,每当您想知道某些东西是如何工作的时候就去那里看看)您可以看到它的作用如下:
If you look at the source code for String.replace(char,char) (also available in src.zip in your JDK installation directory -- a pro tip is to look there whenever you wonder how something really works) you can see that what it does is the following:
- 如果当前字符串中有一个或多个
oldChar
,则复制当前字符串,其中所有出现的oldChar
都被替换为newChar
. - 如果
oldChar
在当前字符串中不存在,则返回当前字符串.
- If there is one or more occurrences of
oldChar
in the current string, make a copy of the current string where all occurrences ofoldChar
are replaced withnewChar
. - If the
oldChar
is not present in the current string, return the current string.
是的,"Mississippi".replace('i', '!')
创建了一个新的 String
对象.同样,以下内容成立:
So yes, "Mississippi".replace('i', '!')
creates a new String
object. Again, the following holds:
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', '!');
:)
Your homework for now is to see what the above code does if you change s1 = s1.replace('i', '!');
to s1 = s1.replace('Q', '!');
:)
1 实际上,改变字符串(和其他不可变对象)是可能的.它需要反思并且非常非常危险,除非您真的有兴趣破坏程序,否则永远不要使用它.
1 Actually, it is possible to mutate strings (and other immutable objects). It requires reflection and is very, very dangerous and should never ever be used unless you're actually interested in destroying the program.
这篇关于Java中字符串的不变性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!