考虑下面的例子。

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!”),并且在replace()方法之后引用str指向不同的对象?


当前回答

字符串是不可变的,这意味着你不能改变对象本身,但是你可以改变对对象的引用。当你调用a = "ty"时,你实际上是将a的引用更改为一个由String文字"ty"创建的新对象。改变一个对象意味着使用它的方法来改变它的一个字段(或者字段是公共的而不是final的,这样它们就可以从外部更新而不需要通过方法访问它们),例如:

Foo x = new Foo("the field");
x.setField("a new field");
System.out.println(x.getField()); // prints "a new field"

而在一个不可变类(声明为final,以防止通过继承修改)(它的方法不能修改它的字段,而且字段总是私有的,建议是final),例如String,你不能改变当前的String,但你可以返回一个新的String,即:

String s = "some text";
s.substring(0,4);
System.out.println(s); // still printing "some text"
String a = s.substring(0,4);
System.out.println(a); // prints "some"

其他回答

我可以说,不可变性是你不能改变字符串本身。假设你有字符串x,它的值是“abc”。现在您不能更改字符串,也就是说,您不能更改“abc”中的任何字符/s。

如果你必须改变字符串中的任何字符,你可以使用一个字符数组并改变它或使用StringBuilder。

String x = "abc";
x = "pot";
x = x + "hj";
x = x.substring(3);
System.out.println(x);

char x1[] = x.toCharArray();
x1[0] = 's';
String y = new String(x1);
System.out.println(y);

输出:

hj
sj

字符串类是不可变的,你不能改变不可变对象的值。 但在String的情况下,如果你改变了String的值,它会在字符串池中创建新的字符串,而不是旧的字符串引用。通过这种方式,字符串是不可变的。 举个例子,

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

它将创建一个字符串“Mississippi”,并将其添加到字符串池 所以现在str指向密西西比。

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

但经过上述操作, 另一个字符串将被创建"M!ss!ss!pp!" 它将被添加到String池。而且 现在str指向M!ss!ss!pp!而不是密西西比州。

通过这种方式,当你改变string对象的值时,它会创建一个新的对象并将其添加到string池中。

让我们再看一个例子

String s1 = "Hello"; 
String s2 = "World"; 
String s = s1 + s2;

上面的3行代码将向字符串池中添加3个字符串对象。 1)你好 2)世界 3) HelloWorld

如果HELLO是你的字符串,那么你不能把HELLO改成HILLO。这个性质叫做不可变性。

你可以有多个指针字符串变量指向HELLO字符串。

但是如果HELLO是char Array,那么你可以将HELLO改为HILLO。例如,

char[] charArr = 'HELLO';
char[1] = 'I'; //you can do this

编程语言具有不可变的数据变量,因此可以作为键、值对中的键使用。

我建议你读一读《Cup Size》——一个关于变量和值传递的故事(续《Cup Size》)。这对阅读上面的文章有很大帮助。

你读过吗?是的。好。

String str = new String();

这将创建一个名为“str”的新“远程控制”,并将其设置为值new String()(或“”)。

例如,在内存中创建:

str --- > ""

str  = "Hello";

这将更改远程控制“str”,但不会修改原始字符串“”。

例如,在内存中创建:

str -+   ""
     +-> "Hello"

str = "Help!";

这将更改远程控件“str”,但不会修改原始字符串“”或远程控件当前指向的对象。

例如,在内存中创建:

str -+   ""
     |   "Hello"
     +-> "Help!"

不可变性意味着实例化对象的值不能改变,你永远不能把“Hello”变成“Help!”

变量str是一个对象的引用,当你给str赋一个新值时,你没有改变它引用的对象的值,你引用的是一个不同的对象。