3

There's plenty of questions about string immutability in Java, for which the author of the question actually re-assigns the reference.

There's however a remarkable case in which it seems there's not a re-assignment of the string:

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

You see that as an actual modification of the string. Try it at home.

I'm pretty sure that this is some kind of syntactic sugar, and gets translated by the compiler in something having the same semantics as:

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

Can someone confirm this fact?

Community
  • 1
  • 1
Dacav
  • 13,590
  • 11
  • 60
  • 87
  • Confirmed. After the `+=` there will be too strings in the heap, "hello" and "hello world". The former will have no reference and will be soon garbage collected. The latter is referenced and will live until released. – gbtimmon Dec 10 '12 at 20:29
  • 1
    On the second line, s is a new object. – jn1kk Dec 10 '12 at 20:30

4 Answers4

5

Wrong.

x += y is just shorthand for x = x + y.
It's still a regular assignment operation, and it does not modify any existing instances.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
4

I can neither confirm nor deny it. If an optimising compiler could prove to itself that no other thread could "see" the initial (pre-+=) value of s then it would be free to optimise away the concatenation and compile the code to the equivalent of

String s = "hello world";

Compilers have a great deal of freedom as to exactly how they translate from source to bytecode, as long as they obey the memory model.

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
  • I'm not sure if that's correct. `"hello world"` is a constant String expression, as is `"hello" + " world"`. But I don't think the OP's code fragment counts as one. Therefore, if you later tested `s == "hello world"` (intentionally using == instead of equals), then whether the concatenation got optimized away or not does matter (do to String interning). What I'm unsure of is whether a constant String created with `+` sugar is _required_ to be a new object, or whether it's simply _allowed_ to be. – yshavit Dec 10 '12 at 22:40
4

It is a new object, original object does not get modified;

This:

public static void main(String[] args) {

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

}

Get translated into this:

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
}

This creates two Strings and adds them into a new String object.

jn1kk
  • 5,012
  • 2
  • 45
  • 72
0

To expand skynorth's answer for those who cannot read Java byte code, given the following source code:

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

When running a JAD decompiler on the compiled class file, you get this Java code:

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

Which is quite self-explanatory and precisely corresponds with the bytecode that skynort posted.

Natix
  • 14,017
  • 7
  • 54
  • 69
  • It might be nice to include some source code from StringBuilder.java to emphasize the fact that is, in fact, a new String object. (definition of `toString()`). `return new String(value, 0, count);` – jn1kk Dec 10 '12 at 21:27