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 :)

M A
  • 71,713
  • 13
  • 134
  • 174
krimat_
  • 142
  • 7

2 Answers2

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
M A
  • 71,713
  • 13
  • 134
  • 174
  • 6
    Sure about the last sentence? [Implementation of `PrintStream#print(boolean)`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/io/PrintStream.java#PrintStream.print%28boolean%29). – Tom Feb 26 '15 at 20:55
  • 1
    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... – krimat_ Feb 26 '15 at 21:01
  • 3
    @krimat but the literal String used to create the `String` is added to the constant pool. – Luiggi Mendoza Feb 26 '15 at 21:03
  • 1
    @Tom You're right. I was referring to the constant pool of the classfile. It's corrected now. Thanks. – M A Feb 26 '15 at 21:08
  • @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??? :) – krimat_ Feb 26 '15 at 21:08
  • 4
    @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. – rgettman Feb 26 '15 at 21:10
  • @immibis Well, this question just "says" `After the println method executes...`, but your remark is right :). – Tom Feb 26 '15 at 21:12
  • @manouti: just for the sake of completeness... and my mental health... can you briefly tell me why the string "summer" does not get created? – krimat_ Feb 26 '15 at 21:16
  • 2
    @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. – M A Feb 26 '15 at 21:18
  • @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"... – krimat_ Feb 26 '15 at 21:23
  • @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 pool – Iłya Bursov Feb 26 '15 at 21:23
  • @Lashane: you cannot be sure when garbage collection occurs, so its safe to assume - for exam's sake - that it will NOT be removed :) – krimat_ Feb 26 '15 at 21:25
  • 3
    @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. – M A Feb 26 '15 at 21:27
  • @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 :) – krimat_ Feb 26 '15 at 21:33
  • @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"`. – M A Feb 26 '15 at 21:39
  • 1
    @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 :) – krimat_ Feb 26 '15 at 21:45
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

Balint Domokos
  • 1,021
  • 8
  • 12
  • 2
    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)`) – Tom Feb 26 '15 at 20:55
  • 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? – krimat_ Feb 26 '15 at 20:57
  • @krimat Interesting question. It might add all String literals if it loads the class, but I don't know for sure. Maybe [manoutis](http://stackoverflow.com/questions/28752489/string-count-in-the-pool-with-println#28752534) way of verifying helps you here. – Tom Feb 26 '15 at 21:00
  • 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? – Balint Domokos Feb 26 '15 at 21:01
  • 2
    @BalintDomokos It matters, because `System.out` is a `PrintStream`. – Tom Feb 26 '15 at 21:07
  • Still don't see. Does "write"'s implementation matter as well then? – Balint Domokos Feb 26 '15 at 21:18
  • 1
    @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. – Tom Feb 26 '15 at 21:21