String count in the pool with println
Asked Answered
H

2

12

I am preparing for the OCA SE 7 exam, and some of these questions are really (!) tricky.

In one of the books Im using I found an error I think, so I would like to confirm the following please...

public static void main(String... args) {
    String autumn = new String("autumn");      // line one
    System.out.println("autumn" == "summer");  // line two
}

After the println method executes, how many String objects are there in the pool?

It is my understanding that: - line one does not add the string to the pool - line two creates "autumn" and "summer" and adds them to the pool So the correct answer in the book is 2.

However, I also think... since Im supposed to be paranoid with the exam questions... that also the string "false" is created and added to the pool... So I think 3 should be the correct answer... or does some other black magic happen like... "true" and "false" are already put into the pool by the JVM by default or something?...

Can someone please confirm?


Edit: after some research I find that it was not fair of me to speak of an 'error' in the book; as a general tip: exam questions are usually formulated in terms of 'the following code'; so they are clearly interested in plain old simple calculation of what the code itself is locally doing. So the scope therefore does not allow inspection of the println(boolean b) implementation or compiler optimizations. Fair enough :)

Hawse answered 26/2, 2015 at 20:49 Comment(1)
That was my point below in the comments...Ernst
B
14

It should be 2 strings: "autumn" and "false". The first is created by the first line. The second is created by the second line because the compiler would optimize it to just:

System.out.println(false);

which ends up calling PrintStream#print(boolean):

public void print(boolean b) {
    write(b ? "true" : "false");
}

This is what happens at runtime, i.e. after the code is executed. However, at the level of the constant pool stored in the bytecode, only 1 string constant is created which is "autumn" in the classfile of the class which contains your main method. You can verify this by running:

javap -c -verbose ClassName
Brynhild answered 26/2, 2015 at 20:53 Comment(16)
Sure about the last sentence? Implementation of PrintStream#print(boolean).Bourgeon
Well the fact that line one creates a string in the pool really blows my mind: I was taught that using the new operator you create a string but you do not add it to the pool...Hawse
@krimat but the literal String used to create the String is added to the constant pool.Dicky
@Bourgeon You're right. I was referring to the constant pool of the classfile. It's corrected now. Thanks.Brynhild
@LuiggiMendoza hm... the book literally says "The code at 1 creates a new String object with the value "autumn". This object is not placed in the String constant pool." Who do I trust??? :)Hawse
@krimat When you create the new String, the string literal "autumn" is already in the pool. The newly created string is not placed in the pool.Spirt
@immibis Well, this question just "says" After the println method executes..., but your remark is right :).Bourgeon
@manouti: just for the sake of completeness... and my mental health... can you briefly tell me why the string "summer" does not get created?Hawse
@krimat Because practically the compiler converts the line System.out.println("autumn" == "summer"); into System.out.println(false); as part of its optimization process. Therefore, the generated bytecode has no reference of "summer" anymore.Brynhild
@manouti: correct me if Im wrong: this optimization happens because... the compiler knows that creating ANY new literal inside of this == expression will always result in the expression being false, regardless of if its "summer" or "kris is going nuts"...Hawse
@manouti just curious, as soon as string variable autumn is not used - java compiler can remove it at all, then only "false" will appear in poolBugaboo
@Lashane: you cannot be sure when garbage collection occurs, so its safe to assume - for exam's sake - that it will NOT be removed :)Hawse
@krimat The compiler knows for sure that autumn is different than summer. Therefore yes, it knows that it should generate false, short-circuiting the string evaluation.Brynhild
@manouti: thank you for your patience :) This question turned out to be a tip of its own iceberg I see... but compiler optimization is something I did not take into account earlier so there is new insight here. Another is: the scope of the exam question should be formulated better, otherwise Im not sure what (not) to take into account. So in this case, its anyone's guess what answer they expect :)Hawse
@krimat You already performed some optimization indirectly in your mind when you said in your question that "false" will be interned in the string pool :) You already "ignored" "summer".Brynhild
@manouti indeed... but I did that on the PrintStream#print(boolean) level... I did not put it back to the System.out.print() level... thats the learning curve of today :)Hawse
E
0

true and false are not String objects, so they do not count. Even though the exam questions are supposed to be tricky, it's goal is to check the understanding of general concepts. Which is in this case: during class loading (before running), the string literals are loaded to the constant pool. So "autumn" and "summer" will be in the constant pool.

It is described here nicely: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html

Ernst answered 26/2, 2015 at 20:53 Comment(7)
The implementation of PrintStream#print(boolean) is: write(b ? "true" : "false");, so it will add "true" and "false" to the pool. (#println(boolean) calls #print(boolean))Bourgeon
Thank you @Tom: that is the implementation that I was looking at, but I suppose only either "true" or "false" will be created since the expression is short-circuit, no?Hawse
@krimat Interesting question. It might add all String literals if it loads the class, but I don't know for sure. Maybe manoutis way of verifying helps you here.Bourgeon
Why should the implementation of PrintStream matter in this case? Are one supposed to know it for the exam? I mean, what if write's implementation creates some more strings? e.g. "stdout" or something?Ernst
@BalintDomokos It matters, because System.out is a PrintStream.Bourgeon
Still don't see. Does "write"'s implementation matter as well then?Ernst
@BalintDomokos Well, if OP is right and this book asks tricky questions and the reader might be supposed to learn to read library implementations, then I guess it matters here. But I don't know this book.Bourgeon

© 2022 - 2024 — McMap. All rights reserved.