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

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


当前回答

在这里看到的

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的内容都会创建一个新对象。也就是说,你不允许改变不可变对象的内容。这就是为什么两个对象的地址是不同的。

其他回答

你实际上得到了一个新字符串的引用,字符串本身没有被改变,因为它是不可变的。这是相关的。

See

维基百科上的不可变对象

你改变了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";

字符串是不可变的,这意味着你不能改变对象本身,但是你可以改变对对象的引用。

当你执行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"

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

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