考虑下面的例子。

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指向不同的对象?


当前回答

我会用一个简单的例子来解释


考虑任何字符数组:例如char[] ={‘h’,‘e’,‘l’,‘l’,”o '}; 和一个字符串: 字符串s =“你好”;


在字符数组上,我们可以执行如下操作:使用迭代数组只打印最后三个字母; 但在字符串中,我们必须创建新的字符串对象并复制所需的子字符串,其地址将在新的字符串对象中。

e.g.

***String s="hello";
String s2=s.substrig(0,3);***

s2有“hel”;

其他回答

字符串类是不可变的,你不能改变不可变对象的值。 但在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

字符串不会改变,但对它的引用会改变。你混淆了不可变性和final字段的概念。如果一个字段被声明为final,那么一旦它被赋值,就不能重新赋值。

我会用一个简单的例子来解释


考虑任何字符数组:例如char[] ={‘h’,‘e’,‘l’,‘l’,”o '}; 和一个字符串: 字符串s =“你好”;


在字符数组上,我们可以执行如下操作:使用迭代数组只打印最后三个字母; 但在字符串中,我们必须创建新的字符串对象并复制所需的子字符串,其地址将在新的字符串对象中。

e.g.

***String s="hello";
String s2=s.substrig(0,3);***

s2有“hel”;

Use:

String s = new String("New String");
s.concat(" Added String");
System.out.println("String reference -----> "+s); // Output: String reference -----> New String

如果你看到这里我使用concat方法来改变原始字符串,即“新字符串”与字符串“添加的字符串”,但我仍然得到了输出,因此它证明了你不能改变string类对象的引用,但如果你通过StringBuilder类做这件事,它将工作。它列在下面。

StringBuilder sb = new StringBuilder("New String");
sb.append(" Added String");
System.out.println("StringBuilder reference -----> "+sb);// Output: StringBuilder reference -----> New String Added String

Object字符串-方法本身是“不可变的”。 此操作不会产生任何更改:“字母”。替换(“bbb”、“aaa”);“

但是分配数据会导致Strings内容的改变:

    letters = "aaa";
    letters=null;
    System.out.println(letters);
    System.out.println(oB.hashCode());
    System.out.println(letters);
    letters = "bbbaaa";
    System.out.println(oB.hashCode());
    System.out.println(letters);

// string Object的hashcode不变。