我在不可变字符串上写了下面的代码。

public class ImmutableStrings {

    public static void main(String[] args) {
        testmethod();
    }

    private static void testmethod() {
        String a = "a";
        System.out.println("a 1-->" + a);
        a = "ty";
        System.out.println("a 2-->" + a);
    }
}

输出:

a 1-->a  
a 2-->ty

这里变量a的值被改变了(尽管许多人说不可变对象的内容不能被改变)。但是说字符串是不可变的到底是什么意思呢?你能给我解释一下这个话题吗?

来源:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html


当前回答

Java字符串是不可变的,字符串将以对象的形式存储值。所以如果你赋值String a="a";它将创建一个对象,值存储在其中,如果你分配值a="ty"意味着它将创建另一个对象存储在其中的值,如果你想清楚地理解,检查字符串的has代码。

其他回答

你不是在改变赋值语句中的对象,而是用另一个不可变对象替换了一个不可变对象。Object String("a")不会变成String("ty"),它会被丢弃,对ty的引用会被写入a中。

相反,StringBuffer表示一个可变对象。你可以这样做:

StringBuffer b = new StringBuffer("Hello");
System.out.writeln(b);
b.append(", world!");
System.out.writeln(b);

在这里,您没有重新分配b:它仍然指向相同的对象,但该对象的内容已经更改。

If some object bar holds a reference to a mutable object foo and encapsulates some of its state in mutable aspects of foo's state, that will allow code which can change those aspects of foo to change the corresponding aspects of bar's state without actually touching bar or even knowing of its existence. Generally, this means that objects which encapsulate their own state using mutable objects must ensure that no references to those objects are exposed to any code which might unexpectedly mutate them. By contrast, if bar holds a reference to an object moo and only uses immutable aspects of moo other than identity to encapsulate its state, then bar can freely expose moo to outside code without worrying about anything the outside code might do to it.

在你的例子中,变量a只是一个字符串对象实例的引用。当你说a = "ty"时,你实际上并没有改变字符串对象,而是将引用指向string类的一个完全不同的实例。

你改变了a指的东西。试试这个:

String a="a";
System.out.println("a 1-->"+a);
String b=a;
a="ty";
System.out.println("a 2-->"+a);
System.out.println("b  -->"+b);

您将看到a和b所指向的对象没有改变。

如果你想阻止你的代码改变a引用的对象,试试:

final String a="a";

在这里看到的

class ImmutableStrings {

    public static void main(String[] args) {
        testmethod();
    }

    private static void testmethod() {
    String a="a";
    System.out.println("a 1-->"+a);
    System.out.println("a 1 address-->"+a.hashCode());

    a = "ty";
    System.out.println("a 2-->"+a);

       System.out.println("a 2 address-->"+a.hashCode());
    }
}

输出:

a 1-->a
a 1 address-->97
a 2-->ty
a 2 address-->3717

这表明无论何时修改不可变字符串对象a的内容都会创建一个新对象。也就是说,你不允许改变不可变对象的内容。这就是为什么两个对象的地址是不同的。