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

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


当前回答

希望下面的代码能澄清你的疑问:

public static void testString() {
    String str = "Hello";
    System.out.println("Before String Concat: "+str);
    str.concat("World");
    System.out.println("After String Concat: "+str);
    StringBuffer sb = new StringBuffer("Hello");
    System.out.println("Before StringBuffer Append: "+sb);
    sb.append("World");
    System.out.println("After StringBuffer Append: "+sb);
}

字符串Concat:你好 字符串后Concat:你好 在StringBuffer追加之前:Hello StringBuffer后追加:HelloWorld

其他回答

字符串是一个char[],包含一系列UTF-16代码单元,该数组的int偏移量和int长度。

为例。

String s

它为字符串引用创建空间。赋值复制周围的引用,但不修改这些引用所引用的对象。

你也应该意识到

new String(s)

并没有做任何有用的事情。它只是创建了另一个实例,支持的数组、偏移量和长度与s相同。很少有理由这样做,因此大多数Java程序员认为这是一种糟糕的做法。

Java双引号字符串,如“my string”,实际上是对内部string实例的引用,因此“bar”是对同一个string实例的引用,而不管它在代码中出现了多少次。


“hello”创建了一个被池化的实例,而新的String(…)创建了一个非池化的实例。尝试system . out。println((“hello”= =“你好 ") + "," + ( 新的字符串“hello”= =“你好 ") + "," + ( 新的字符串(“hello”)= =新的字符串(“hello”)));你应该看到真,假,假

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

在这里看到的

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

在你的例子中,a首先指向“a”,然后指向“ty”。你没有改变任何String实例;你只是改变了a引用的String实例。例如,这个:

String a = "a";
String b = a; // b refers to the same String as a
a = "b"; // a now refers to a different instance
System.out.println(b);

打印"a",因为我们从未改变b所指向的String实例。

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.