Java的字符串不变性,带有“+ =”运算符

时间:2012-12-10 20:27:36

标签: java string immutability

plenty questions {{3}}关于Java中的字符串不变性,问题的作者实际上重新分配了引用。

然而,有一个非常明显的案例,似乎没有重新分配字符串:

String s = "hello";
s += " world";

您将其视为字符串的实际修改。在家尝试。

我很确定这是某种语法糖,并且被编译器翻译成具有相同语义的东西:

String s = "hello";
s = s + " world";

有人可以证实这个事实吗?

4 个答案:

答案 0 :(得分:5)

错误。

x += y只是x = x + y的简写 它仍然是一个常规的赋值操作,它不会修改任何现有的实例。

答案 1 :(得分:4)

我既不能确认也不能否认。如果优化编译器可以向自己证明没有其他线程可以“看到”s的初始(pre - +=)值,则可以自由地优化掉串联并将代码编译为等效的

String s = "hello world";

只要编译器遵循内存模型,编译器就可以完全自由地将它们从源代码转换为字节代码。

答案 2 :(得分:4)

这是一个新对象,原始对象不会被修改;

此:

public static void main(String[] args) {

    String s = "hello";
    s += " world";
    System.out.println(s);

}

翻译成:

public static void main(java.lang.String[]);
    Code:
        0: ldc           #2                  // String hello
        2: astore_1
        3: new           #3                  // class java/lang/StringBuilder
        6: dup
        7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        10: aload_1
        11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        14: ldc           #6                  // String  world
        16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        22: astore_1
        23: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
        26: aload_1
        27: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        30: return
}

这会创建两个String并将它们添加到新的String对象中。

答案 3 :(得分:0)

为那些无法读取Java字节代码的人扩展skynorth的答案,给出以下源代码:

public static void main(String... args) {
    String s = "hello";
    s += "world";
}

在已编译的类文件上运行JAD decompiler时,您将获得以下Java代码:

public static void main(String args[]) {
    String s = "hello";
    s = (new StringBuilder(String.valueOf(s))).append("world").toString();
}

这是非常不言自明的,并且与skynort发布的字节码精确对应。