2

The code in the following snippet just compares string references.

String str1 = "mystring9";
String str2 = "mystring"+String.valueOf(9);

System.out.println(str1==str2);

In this case, str1==str2 returns false.


The following segment of code also returns false.

String str1 = "mystring9";
String str2="mystring"+str1.length();

System.out.println(str1==str2);

The following code however, returns true.

String str1 = "mystring9";
String str2 = "mystring"+9;

System.out.println(str1==str2);

I think, the expression "mystring"+9 in this code should internally be evaluated to String.valueOf(9) though why do the first two examples return different output than the preceding example?

Tiny
  • 27,221
  • 105
  • 339
  • 599

6 Answers6

3

The Java compiler will pre-evaluate all constant-only operations. (this is called constant folding)

Therefore, "A" + "b" + 3 compiles to "Ab3".

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Thank you but as [this](http://stackoverflow.com/a/11408526/1037210) answer states according to its example, "*The compiler converts `"x = "+x;` into a `StringBuilder` internally and uses `.append(int)` to "add" the integer to the string.*" If it is the case then, the last example in this question i.e `"mystring"+9;` should internally be converted to `new StringBuilder("mystring").append(9).toString();`. Does it happen at compile-time itself? – Tiny Oct 25 '13 at 22:13
  • @Tiny: The compiler only does that when there isn't a faster alternative. If both operands are known at compile-time, it compiles them all to a single literal. – SLaks Oct 27 '13 at 00:26
2

Because the compiler is smart enough to see that

String str2 = "mystring"+9;

is a constant expression, so it evaluates it at compile time, leading to a literal string "mystring9".

String literals are stored in a pool, so that they can be reused, that's why str1 and str2 refer to the same String object (which you can check by comparing them with ==).

Jesper
  • 202,709
  • 46
  • 318
  • 350
  • Thank you but as [this](http://stackoverflow.com/a/11408526/1391249) answer states according to its example, "The compiler converts "x = "+x; into a StringBuilder internally and uses .append(int) to "add" the integer to the string." If it is the case then, the last example in this question i.e "mystring"+9; should internally be converted to new StringBuilder("mystring").append(9).toString();. Does it happen at compile-time itself? – Tiny Oct 25 '13 at 22:36
  • There are most likely special cases, like this one, where the compiler recognises that the result will always be the same, so it can just find the result and put it in the output code as a constant. If you really want to know how the compiler works, you should look up the source code of the compiler, which you can find in the OpenJDK project. – Jesper Oct 26 '13 at 06:48
2

This is because the compiler can create String's during compilation time - i.e.:

"mystring"+9becomes "mystring9"

FazoM
  • 4,777
  • 6
  • 43
  • 61
  • Thank you but as [this](http://stackoverflow.com/a/11408526/1391249) answer states according to its example, "The compiler converts "x = "+x; into a StringBuilder internally and uses .append(int) to "add" the integer to the string." If it is the case then, the last example in this question i.e "mystring"+9; should internally be converted to new StringBuilder("mystring").append(9).toString();. Does it happen at compile-time itself? – Tiny Oct 25 '13 at 22:36
2

depends when the code is compiled.

the last one is resvoled at the compile time. You can also add one more example with

String str1 = "mystring9";
String str2 = "mystring"+"9";

System.out.println(str1==str2);

you will see that returns true too

X-Pippes
  • 1,170
  • 7
  • 25
  • Thank you but as [this](http://stackoverflow.com/a/11408526/1391249) answer states according to its example, "The compiler converts "x = "+x; into a StringBuilder internally and uses .append(int) to "add" the integer to the string." If it is the case then, the last example in this question i.e "mystring"+9; should internally be converted to new StringBuilder("mystring").append(9).toString();. Does it happen at compile-time itself? – Tiny Oct 25 '13 at 22:38
2
String str1 = "mystring9";

Executing this line create a string "myString9" in String literal pool for reuse.

According to JLS section 15.18.1: String Concatenation Operator +

If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.

so String str2 = "myString"+9 results in "myString9", hence str1 and str2 are holding the same reference to literal pool and str1==str2 gives true.

Sage
  • 15,290
  • 3
  • 33
  • 38
  • Thank you but as [this](http://stackoverflow.com/a/11408526/1391249) answer states according to its example, "The compiler converts "x = "+x; into a StringBuilder internally and uses .append(int) to "add" the integer to the string." If it is the case then, the last example in this question i.e "mystring"+9; should internally be converted to new StringBuilder("mystring").append(9).toString();. Does it happen at compile-time itself? – Tiny Oct 25 '13 at 22:37
  • `string conversion` doesn't happen in compile time rather as the specification says, it happens in run time – Sage Oct 25 '13 at 22:46
1
String str1 = "mystring9";
String str2 = "mystring"+9;

System.out.println(str1==str2);

That is true because they both resolved at compile time.

Where as the other two cases on the top resolved at runtime.

when we concat strings with (+) operator JVM returns new StringBuilder(string...).toString()

That Which creates a new String instance in heap memory" isn't true when you're concatenating String literals in the source code,

e.g., "test" + "test". That kind of concatenation is done at compile time, and it's the same as if you had written "testtest".

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • Thank you but as [this](http://stackoverflow.com/a/11408526/1391249) answer states according to its example, "The compiler converts "x = "+x; into a StringBuilder internally and uses .append(int) to "add" the integer to the string." If it is the case then, the last example in this question i.e "mystring"+9; should internally be converted to new StringBuilder("mystring").append(9).toString();. Does it happen at compile-time itself? – Tiny Oct 25 '13 at 22:38