考虑下面的例子。

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


当前回答

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不变。

其他回答

或者你可以试试:

public class Tester
{
public static void main(String[] args)
{
 String str = "Mississippi"; 
 System.out.println(str); // prints Mississippi 
 System.out.println(str.hashCode());

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

这将显示hashcode是如何变化的。

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

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

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

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

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

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

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

str引用的对象可以更改,但实际的String对象本身不能更改。

包含字符串“Hello”和“Help!”的String对象不能改变它们的值,因此它们是不可变的。

String对象的不可变性并不意味着指向该对象的引用不能改变。

防止str引用更改的一种方法是将其声明为final:

final String STR = "Hello";

现在,尝试将另一个String赋值给STR将导致编译错误。

对于那些想知道如何在Java中打破字符串不变性的人…

Code

import java.lang.reflect.Field;

public class StringImmutability {
    public static void main(String[] args) {
        String str1 = "I am immutable";
        String str2 = str1;

        try {
            Class str1Class = str1.getClass();
            Field str1Field = str1Class.getDeclaredField("value");

            str1Field.setAccessible(true);
            char[] valueChars = (char[]) str1Field.get(str1);

            valueChars[5] = ' ';
            valueChars[6] = ' ';

            System.out.println(str1 == str2);
            System.out.println(str1);
            System.out.println(str2);           
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}

输出

true
I am   mutable
I am   mutable