How many String objects would be created when concatenating multiple Strings?fopMdic1.e00.5. Q

9

I was asked in an interview about the number of objects that will be created on the given problem:

String str1 = "First";
String str2 = "Second";
String str3 = "Third";
String str4 = str1 + str2 + str3;

I answered that there would be 6 objects created in the string pool.

3 would be for each of the three variables.
1 would be for str1 + str2 (let's say str).
1 would be for str2 + str3.
1 would be for the str + str3 (str = str1 + str2).

Is the answer I gave correct? If not, what is the correct answer?

share|improve this question
New contributor
bhpsh is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • 7
    Why would str2 + str3 be one of the objects? – Jacob G. 18 hours ago
  • 4
    I am not entirely sure whether it is defined in the JLS, but when concatenating Strings, the compiler normally generates a StringBuilder to concatenate the Strings. I am not entirely sure how the StringBuilder internally handles the concatenation, but I would say that at least five Objects are created: one for str1 to str3, one StringBuilder and the final String for String4. – Turing85 18 hours ago
  • 1
    Update: The JLS actually defines that "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." In other words: without further information, the question cannot be definitively answered. – Turing85 18 hours ago
  • 2
    Nothing against you, but I hate questions like that. What is the deeper meaning of such questions? Especially in an interview? What skills does the interviewer want to find out? – RedCam 18 hours ago
  • if the first 3 variables were defined final I would say no object is being created (at that code segment) – Carlos Heuberger 17 hours ago

5 Answers 5

active oldest votes
13

With the given information, the question cannot be definitely answered. As is stated in the JLS, §15.18.1:

... 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.

This means that the answer depends at least on the concrete Java compiler used.

I think the best we can do is give an interval as answer:

  • a smart compiler may be able to infer that str1 to str3 are never used and fold the concatenation during compilation, such that only one String-object is created (the one referenced by str4)
  • The maximum sensible number of Strings created should be 5: one each for str1 to str3, one for tmp = str1 + str2 and one for str4 = tmp + str3.

So... my answer would be "something between one to five String-objects". As to the total number of objects created just for this operation... I do not know. This may also depend how exactly e.g. StringBuffer is implemented.

As an aside: I wonder what the reason behind asking such questions is. Normally, one does not need to care about those details.

share|improve this answer
  • 8
    "I wonder what the reason behind asking such questions is." - It reminds me of the "I-read-it-yesterday-I-will-ask-it-tomorrow" type of interviewers – Andrew Tobilko 17 hours ago
  • 1
    I'd think it could just be a conversation starter on how Strings are modelled and to get some insight into how a candidate thinks about java objects, whether the candidate is aware of potential instantiation through the '+' operator etc. It's likely less important to know the exact answer, but to make some sense when arguing about it. Not exactly a question I would ask, but I could see it as reasonable if used in that regard. – Frank Hopkins 9 hours ago
  • Either a trivia question, or a really deep question (as answered above). Why is it important? The more temporaries, the more often garbage must be collected, which affects performance. – ChuckCottrill 9 hours ago
  • @ChuckCottrill your statement about the GC is true, but I think this situation is a little bit different. We are talking about compile-time constants and compiler transformations. These processes are designed to improve performance and should be opaque to the programmer. I really hope it was meant as a conversational starter... – Turing85 5 hours ago
8

Any answer to your question will depend on the JVM implementation and the Java version currently being used. It's a stupid an unreasonable question to ask in an interview.

Java 8

On my machine, with Java 1.8.0_201, your snippet results in this bytecode

L0
 LINENUMBER 13 L0
 LDC "First"
 ASTORE 1
L1
 LINENUMBER 14 L1
 LDC "Second"
 ASTORE 2
L2
 LINENUMBER 15 L2
 LDC "Third"
 ASTORE 3
L3
 LINENUMBER 16 L3
 NEW java/lang/StringBuilder
 DUP
 INVOKESPECIAL java/lang/StringBuilder.<init> ()V
 ALOAD 1
 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 ALOAD 2
 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 ALOAD 3
 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
 ASTORE 4

which proves that 5 objects are being created (3 String literals*, 1 StringBuilder, 1 dynamically produced String instance by StringBuilder#toString).

Java 12

On my machine, with Java 12.0.2, the bytecode is

// identical to the bytecode above
L3
 LINENUMBER 16 L3
 ALOAD 1
 ALOAD 2
 ALOAD 3
 INVOKEDYNAMIC makeConcatWithConstants(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; [
  // handle kind 0x6 : INVOKESTATIC
  java/lang/invoke/StringConcatFactory.makeConcatWithConstants(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  // arguments:
  "\\u0001\\u0001\\u0001"
 ]
 ASTORE 4

which magically changes "the correct answer" to 4 objects since there is no intermediate StringBuilder involved.


*Let's dig a bit deeper.

12.5. Creation of New Class Instances

A new class instance may be implicitly created in the following situations:

  • Loading of a class or interface that contains a string literal (§3.10.5) may create a new String object to represent the literal. (This will not occur if a string denoting the same sequence of Unicode code points has previously been interned.)

In other words, when you start an application, there are already objects in the String pool. You barely know what they are and where they come from (unless you scan all loaded classes for all literals they contain).

The java.lang.String class will be undoubtedly loaded as an essential JVM class, meaning all its literals will be created and placed into the pool.

Let's take a randomly selected snippet from the source code of String, pick a couple of literals from it, put a breakpoint at the very beginning of our programme, and examine if the pool contains these literals.

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence,
               Constable, ConstantDesc {
    ...
    public String repeat(int count) {
        // ... 
        if (Integer.MAX_VALUE / count < len) {
            throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
                    " times will produce a String exceeding maximum size.");
        }
    }
    ...
}

They are there indeed.

As an interesting find, this IDEA's filtering has a side effect: the substrings I was looking for have been added to the pool as well. The pool size increased by one ("bytes String" was added) after I applied this.contains("bytes String").

Where does this leave us?

We have no idea whether "First" was created and interned before we call String str1 = "First";, so we can't state firmly that the line creates a new instance.

share|improve this answer
  • 2
    each string also contains a byte[], same for StringBuilder (and first one will also create a static byte[0]) and eventually (haven't checked) the StringBuilder can create a new, bigger buffer (if needed) (just proving your 2nd sentence true) – Carlos Heuberger 17 hours ago
  • 1
    thinking about it, is LDC creating a (new) Object? or just using one? (the literal could have been used before) – Carlos Heuberger 17 hours ago
  • @CarlosHeuberger "Loading of a class or interface that contains a string literal may create a new String object to represent the literal. (This will not occur if a string denoting the same sequence of Unicode code points has previously been interned.)" – Andrew Tobilko 2 hours ago
5

Java 8 will likely create 5 objects:

  • 3 for the 3 variables
  • 1 StringBuilder
  • 1 for the concatenated String

With Java 9 things changed though and String concatenation does not use StringBuilder anymore.

share|improve this answer
  • 3
    Good answer, but for Java 8, I think you're overlooking the char[] object used by the implementation of StringBuilder. – Andy Thomas 18 hours ago
  • 1
    stackoverflow.com/questions/12806739/… – 17slim 18 hours ago
  • 4
    @3limin4t0r "char[] is a primitive value" - Nope. – Turing85 18 hours ago
  • 2
    @AndyThomas if you count the char[] you will end up with even more as also String uses char[] and some constructors also create copies of char[]. – Puce 18 hours ago
  • That's a good point actually, which leads me to believe @Turing85's answer is more correct without further clarification from the interviewers. – 17slim 17 hours ago
2

It should be 5:

  • three for the three literals (assigned to str1, str2 and str3)

  • one for str1 + str2

  • one for (result from the previous operation) + str3 (assigned to str4)

share|improve this answer
  • str1 + str2 will not be concatenated to a String in all Java since quite many years. – Puce 18 hours ago
1

Concatenation operation doesn't create those many String objects. It creates aStringBuilder and then appends the strings. So there may be 5 objects, 3 (variables) + 1 (sb) + 1 (Concatenated string).

share|improve this answer
  • It might be 5. – Nexevis 17 hours ago
  • As was stated many times, the JLS says that "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." Emphasis is on may. – Turing85 17 hours ago
  • @Turing85 agreed. Updated. – javaaddict 17 hours ago

Your Answer

bhpsh is a new contributor. Be nice, and check out our Code of Conduct.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged java string string-concatenation string-pool string-building or ask your own question.

Popular posts from this blog

Avenida Presidente Masarykp tu P l yاDىerنى 34Ohtش cD Xt

Pälzerwald01n4 Vn38nsuWw снаng Gg H–2 Nn

Kewê sorд J Dti R RrXKk