Literal string creation vs String object creation
Asked Answered
M

3

7

How many String object are created

I am studying for the SCJP I cant seem to get my head round this String problem. I seem to see several possible answers depending on how i look at a question.

In the following initialization, how many string objects are created?

String s1 = "A" + "B" + "C" + "D";
System.out.println(s1)

Initially i thought 5 objects, i.e.

"A"
"B"
"C"
"D"
"ABCD"

But then thinking about it i am not really sure because for example will the compiler concatenate "A" + "B" as one object? i.e creating 7 objects?

"A"
"B"
"C"
"D"
"AB"
"ABC"
"ABCD" 

Also, how many objects will be created if the code was changed to be

String s1 = new String("A" + "B" + "C" + "D");
System.out.println(s1);

And finally how about:

String s1 = "A";
String s2 = new String("A");

In the above example i think only 2 objects will be created

object 1 - "A"
object 2 - a String object that refers to the "A" object above.

Is this correct or will they not be related? i.e. the object referred to from the constant pool will be different from the one referred to by the s2 reference.

Thanks

Edit

Also, please note i am interested in knowing the total number of objects created including those that are discarded not just those that eventually end up in the constant pool.

Edit

Looking at Jon's answer i might have totally misunderstood the way the objects are created. I know that a String is created only once in the constant pool and it is reused but im not sure of the process that goes through when the 'final' string is constructed. Here is the section from the book i am reading which seems to suggest that temporary objects get created which is a complete opposite to the answers here. (Or maybe the book is wrong or i misunderstood the book)

The code sample was

String s1 = "spring ";  
String s2 = s1 + "summer ";  
s1.concat("fall ");  
s2.concat(s1);  
s1 += "winter";  
System.out.println(s1 + " " + s2);

The question was

What is the output? For extra credit, how many String objects and how many reference varibles were created prior to the println statement.

And the answer

The result of this code fragment is spring water spring summer. There are two reference variables, s1 and s2. There were a total of eight String objects created as follows "spring", "summer" (lost), "spring summer", "falls"(lost), "spring fall" (lost), "spring summer spring" (lost), "winter" (lost), "spring winter" (at this point "spring" is lost). Only two of the eight String objects are not lost in this process

Thanks

Maniemanifest answered 29/11, 2011 at 19:39 Comment(3)
You could start answering this for yourself by looking at the generated bytecode.Elvaelvah
Your book example is very different from the original question you asked us. The difference between the example you started with and your last edit is s1 = "A"; s2 = s1 + "B" vs "A" + "B". The compiler turns the second one into "AB" before anything ever runs. The first one runs as-is when you execute the code.Leptospirosis
Oh so the compiler will build the string differently if the expression is only made of literals compared to when there is a mixture of string literals and reference variables that point to strings?Maniemanifest
F
13

The compiler will concatenate the whole of "A" + "B" + "C" + "D" into a single constant - so in your first example, only a single string ends up created at all. That same string will be reused if you execute the same code multiple times. The constant is put in the class file, and when the class is loaded the VM checks whether an equal string is already in the string pool - so it will reuse it even if you have the same code in multiple classes.

You can verify that only a single string is in the constant pool within the class with javap:

javap -v Test

Constant pool:
   #1 = Methodref   #6.#17     //  java/lang/Object."<init>":()V
   #2 = String      #18        //  ABCD
   #3 = Fieldref    #19.#20    //  java/lang/System.out:Ljava/io/PrintStream;

However, here:

String s1 = "A";
String s2 = new String("A");

you do end up with two separate string objects. One (the constant) will be reused every time you execute the code (and is shared between the two statements), and a new one will be created due to the constructor call each time.

So for example, this method:

public static void foo() {
    for (int i = 0; i < 5; i++) {
        String s1 = "A";
        String s2 = new String("A");
    }
}

... will end up using six string objects - one for the constant, and five new ones created each time you call the method.

Fluky answered 29/11, 2011 at 19:44 Comment(15)
And how about the string pool and the concept of Object Oriented Programming? I think in the code example only one object is created.Chubby
@MartijnCourteaux What does the concept of OOP have to do with it?Epicurean
Thanks. See the Edit. I was interested in the total objects created even those that are discarded before the final string is constructed.Maniemanifest
@MartijnCourteaux: The string pool is used for constants, but if you call the String constructor it will create a new object.Fluky
@ziggy: Yes, that's what my answer covers.Fluky
There are some "static bytes" in the string pool, which represents the string object. OOP means: object.method() was in C method(object). So the methods of the String class are applied on the bytes of the String pool. But I could be wrong...Chubby
@JonSkeet: Yes, agreed. But what I mean is that a constant in the string pool isn't a new object.Chubby
@MartijnCourteaux: The OP asked about String objects, not bytes. There's a big difference. And in fact, I believe the String constructor will always copy the contents anyway.Fluky
@JonSkeet: Yes, it copies always the content (as far as I know). But what I think is that the string pool doesn't contain objects. Or am I wrong?Chubby
@MartijnCourteaux: As far as I'm aware, the String pool does contain objects. It at least acts as if it does. What sort of test would you have for whether that's the case or not?Fluky
@MartijnCourteaux I think you're wrong, according to the intern docs, which states that String objects are added to the pool. OTOH, I could see that being implementation-dependent. But in this case, that's not the issue--it's that new does exactly that, creates a new String, regardless of whether or not it's interned.Epicurean
@JonSkeet: I guess you will be right. I'm only 16 years old. I guess you are the one with experience. After some thinking: I think you are indeed right. It sounds indeed logic that it contains Objects.Chubby
@Jon, in your example, s2 will refer to a new String object. Will this new String object be using the same String literal "A" as the one in the pool or will it be using its own copy? (Hope that makes sense)Maniemanifest
@MartijnCourteaux We don't care about age or experience :) Just right-ness... I'm all old and crusty, and I'm still wrong a whole bunch.Epicurean
@ziggy: As you say, it refers to a new String object. You call a constructor, it creates a new object. It will be copied from the object in the constant pool, but after the constructor has finished they're basically independent.Fluky
O
4

How many objects created?

String s1 = "A" + "B" + "C" + "D";
System.out.println(s1)

One or none. This is reduced to one String literal which could be already loaded.

String s1 = new String("A" + "B" + "C" + "D");
System.out.println(s1);

This always creates an extra object.

BTW: A string usually consists of two objects, the String and the char[] it wraps.

Oscine answered 29/11, 2011 at 19:49 Comment(0)
C
2
String s1 = "A" + "B" + "C" + "D";

The compiler will create only one string literal "ABCD" and put it in the String pool. One object will be created (the one in the String Pool).


String s1 = new String("A" + "B" + "C" + "D");

Same here, except that you are copying it from the String literal. So, 2 object will be created here. One by the new and one in the String Pool.


String s1 = "A";
String s2 = new String("A");

Same here, "A" will be a constant in the string pool. The constructor will copy it. So here two objects will be created.

Chubby answered 29/11, 2011 at 19:44 Comment(3)
Mmm, not sure about that second one--an explicit new should create a new object.Epicurean
Thanks. See the Edit. I was interested in the total objects created even those that are discarded before the final string is constructed.Maniemanifest
Fixed this answer. Check out the discussion at JonSkeet his answer.Chubby

© 2022 - 2024 — McMap. All rights reserved.