25

I have a long string that doesn't fit the width of the screen. For eg.

String longString = "This string is very long. It does not fit the width of the screen. So you have to scroll horizontally to read the whole string. This is very inconvenient indeed.";

To make it easier to read, I thought of writing it this way -

String longString = "This string is very long." + 
                    "It does not fit the width of the screen." +
                    "So you have to scroll horizontally" +
                    "to read the whole string." +
                    "This is very inconvenient indeed.";

However, I realized that the second way uses string concatenation and will create 5 new strings in memory and this might lead to a performance hit. Is this the case? Or would the compiler be smart enough to figure out that all I need is really a single string? How could I avoid doing this?

CodeBlue
  • 14,631
  • 33
  • 94
  • 132

3 Answers3

44

I realized that the second way uses string concatenation and will create 5 new strings in memory and this might lead to a performance hit.

No it won't. Since these are string literals, they will be evaluated at compile time and only one string will be created. This is defined in the Java Language Specification #3.10.5:

A long string literal can always be broken up into shorter pieces and written as a (possibly parenthesized) expression using the string concatenation operator +
[...]
Moreover, a string literal always refers to the same instance of class String.

  • Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.
  • Strings computed by concatenation at run-time are newly created and therefore distinct.

Test:

public static void main(String[] args) throws Exception {
    String longString = "This string is very long.";
    String other = "This string" + " is " + "very long.";

    System.out.println(longString == other); //prints true
}

However, the situation situation below is different, because it uses a variable - now there is a concatenation and several strings are created:

public static void main(String[] args) throws Exception {
    String longString = "This string is very long.";
    String is = " is ";
    String other = "This string" + is + "very long.";

    System.out.println(longString == other); //prints false
}
Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 1
    I think he's asking whether it will create a String for `This string` and `This string is`. – David B Aug 16 '12 at 14:28
  • I see, so new strings are created in memory only if variables hold them? – CodeBlue Aug 16 '12 at 14:31
  • @CodeBlue: In other words, if the strings being concatenated are String LITERALS. – kosa Aug 16 '12 at 14:34
  • 1
    @CodeBlue yes, you will only have one string created if and only if you concatenate string literals. – assylias Aug 16 '12 at 14:35
  • @assylias, a related question - Wouldn't Java's string pooling mechanism lead to longString and other being the same string? – CodeBlue Aug 16 '12 at 14:38
  • @CodeBlue In my first example they are the same (that was the point of the example: `==` returns true!) in the second they aren't (`==` returns false). – assylias Aug 16 '12 at 14:39
  • @assylias , Yes, I got that, but I think I misunderstand pooling in that case. – CodeBlue Aug 16 '12 at 14:40
  • @CodeBlue What do you find confusing? – assylias Aug 16 '12 at 14:41
  • @assylias I always thought that if two strings contain the same characters, then Java's pooling mechanism will treat them as the same string. From your example (and I tested it myself as well), it is shown that this is not the case. – CodeBlue Aug 16 '12 at 14:42
  • 2
    @CodeBlue Only string literals are pooled. String created at runtime are not. Unless you force them to go into the pool by using the `intern()` method. For example, in the second code snippet, you can try to use `String other = ("This string" + is + "very long.").intern();` to see the difference. – assylias Aug 16 '12 at 14:45
  • What if i reverse a String? Will it create a new instance? – Akash5288 Jan 10 '14 at 12:29
  • 1
    @akash746 I'm not sure I understand your question. It is proably best to ask it as a separate question with additional details. – assylias Jan 10 '14 at 16:20
  • @assylias did you taken consideration of compiler optimization ? – sailor Oct 28 '17 at 02:31
  • @sailor I'm not sure what you mean - the compiler must be compliant with the specifications... – assylias Oct 28 '17 at 18:18
  • An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression. https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.18.1 thanks to rgettman – sailor Nov 01 '17 at 01:33
  • I understand your point - I was replying to the memory aspect of the question only, not performance, and in my second example several strings are created regardless of compiler optimisations. BTW javac will introduce a StringBuilder in my second example (not a StringBuffer unless you use a very old version). Also note that this changes in Java 9: https://stackoverflow.com/questions/46512888/how-is-string-concatenation-implemented-in-java-9. – assylias Nov 01 '17 at 07:05
  • 1
    It worth noting that if we add the `final` modifier to `is` in your second example, the `" is "` will be treated as literal therefore producing `true` in the output. – Igor Melnichenko Feb 20 '18 at 13:46
8

Does concatenating strings in Java always lead to new strings being created in memory?

No, it does not always do that.

If the concatenation is a compile-time constant expression, then it is performed by the compiler, and the resulting String is added to the compiled classes constant pool. At runtime, the value of the expression is the interned String that corresponds to the constant pool entry.

This will happen in the example in your question.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

Please check below snippet based on your inputs:

String longString = "This string is very long. It does not fit the width of the screen. So you have to scroll horizontally to read the whole string. This is very inconvenient indeed.";

String longStringOther = "This string is very long. " + 
        "It does not fit the width of the screen. " +
        "So you have to scroll horizontally " +
        "to read the whole string. " +
        "This is very inconvenient indeed.";

System.out.println(" longString.equals(longStringOther) :"+ longString.equals(longStringOther));      
System.out.println(" longString == longStringother : " + (longString == longStringOther ));

Output:

longString.equals(longStringOther) :true
longString == longStringother : true

1st Case : Both Strings are equal ( have same content)

2nd Case : Shows that there is only one String after concatenation. So only one String is created.

rai.skumar
  • 10,309
  • 6
  • 39
  • 55