5

As far as I know, StringBuilder helps to reduce memory usage by not creating temporary string instances in the string pool during concats. But, what happens if I do sth like this:

StringBuilder sb = new StringBuilder("bu");
sb.append("b"+"u");

Does it compile into

sb.append("b");
sb.append("u");

? Or it depends on optimalization flags? Or I loose the whole benefit if stringbuilders? Or this quetion makes no sense? :)

4 Answers 4

8

It compiles to sb.append("bu"), because the compiler translates the concatenation of multiple String litterals to a single String litteral.

If you had

String a = "a";
sb.append(a + "b");

it would compile it to

String a = "a";
String temp = a + "b"; // useless creation of a string here
sb.append(temp);

So you should prefer

sb.append(a);
sb.append("b");

in this case.

Sign up to request clarification or add additional context in comments.

4 Comments

Is this something relatively new to Java? I've always been led to belive string concatenation would result in multiple strings as they are immutable? Or does this only apply when concatenating String variables?
No, it's not new. It's very useful to be able to properly format (on several lines) a long string literal, like a long SQL or JPQL query, for example.
for the 2nd code sample not only a String will be created, also an additional StringBuilder will be created.
@JBNizet: Given String cd = "cd";, how does the following String get optimized? String abcdef = "a" + "b" + cd + "e" + "f";?? Thanks!
7

Since "b" + "u" is an expression which is evaluated at compile time, it will be compiled just as if you had "bu".

 0: new #2; //class StringBuilder
 3: dup
 4: ldc #3; //String bu
 6: invokespecial   #4; //Method StringBuilder."<init>":(String;)V
 9: astore_1
10: aload_1
11: ldc #3; //String bu
13: invokevirtual   #5; // StringBuilder.append:(String;)LStringBuilder;

If you on the other hand had two string variables, this optimization wouldn't kick in:

The following snippet...

StringBuilder sb = new StringBuilder("bu");
String b = "b", u = "u";

sb.append(b + u);

...gets compiled as:

0:  new #2; //class StringBuilder
3:  dup
4:  ldc #3; //String bu
6:  invokespecial   #4; //Method StringBuilder."<init>":(String;)V
9:  astore_1
10: ldc #5; //String b
12: astore_2
13: ldc #6; //String u
15: astore_3
16: aload_1
17: new #2; //class StringBuilder
20: dup
21: invokespecial   #7; //Method StringBuilder."<init>":()V
24: aload_2
25: invokevirtual   #8; //Method StringBuilder.append:(String;)StringBuilder;
28: aload_3
29: invokevirtual   #8; //Method StringBuilder.append:(String;)StringBuilder;
32: invokevirtual   #9; //Method StringBuilder.toString:()String;
35: invokevirtual   #8; //Method StringBuilder.append:(String;)StringBuilder;

I.e. something similar to

StringBuilder sb = new StringBuilder("bu");
String b = "b", u = "u";

StringBuilder temp = new StringBuilder();
temp.append(b);
temp.append(b);
String result = temp.toString();

sb.append(result);

As you can see in line 17-21 an extra StringBuilder is created for the purpose of concatenating a and b. The resulting String of this temporary StringBuilder is then fetched on line 32 and appended to the original StringBuilder on line 35.


(The bytecode was generated by the javap command which is part of the JDK. Try it out, it's really simple!)

7 Comments

You guessed what I really wanted to ask :) So optimalization happens when I have literals only, in case of variables, always use append.
@aioobe: Given String cd = "cd";, are the following two equivalent as well? String abcdef = "a" + "b" + cd + "e" + "f"; <==>String abcdef = "ab" + cd + "ef";`? Thanks!
@Gevorg, I believe so, why don't you try it out with javap? :-)
Hahah, it's not. Just do javac Test.java and then javap -c Test.
@aioobe: I did it, it was glorious! :) It compiles to "ab" + cd + "e" + "f"; I tried with different inputs as well, basically only the literals before the variable get optimized. Very interesting.. I guess it might be related to the natural order of '+'..
|
0

No, the "b" + "u" will create an immutable b string, an immutable u string, and then create a third immutable bu string that gets passed into the StringBuilder instance.

8 Comments

No it won't. See @aioobe's answer.
I can't believe the compiler is not smart enough to not create the single letter literals, or, without that much negation, I believe the compiler is smart enough to only create the bu string.
@CarlosHeuberger - it is not "smartness". It is simply a matter of implementing the Java Language Specification.
@Stephen - to be read as: the people who developed and implemented the compiler are smart enough...
@CarlosHeuberger - reading and implementing the spec is your definition of smart? To be fair though, there is a good chance that the spec mirrored the first compiler not the other way around.
|
-1

WRONG:

StringBuilder sb = new StringBuilder();
sb.append("b"+"u");

CORRECT:

StringBuilder sb = new StringBuilder();
sb.append("b").append("u");

BEST: //Since you knew what's going to be in there already! ;)

StringBuilder sb = new StringBuilder();
sb.append("bu");

:)

EDIT

I guess my answer above is not correct when dealing with literals only...

:/

3 Comments

Actually, the "WRONG" version is equivalent to the "BEST" one. See @aioobe's answer.
@StephenC: Do you know how/if/why the following gets optimized by the compiler: `String abcde = "a" + "b" + c + "d" + "e";?
@Gevorg - I know it does because the JLS says it does, and if a compiler didn't do this then it wouldn't be a valid Java compiler.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.