4

Can you please clarify me, how many objects will be created in below case and why? I am slightly confused with this.

String s1 = "cat";

String s2 = "cat";

String s3 = "c"+"at";

String s4 = new String("cat");

String s5 = "kitty"+"cat";

String s6 = new String("kittycat");

String s7 = s5;

String s8= new String(s5); // Newly Added in this Question
Kumar
  • 183
  • 1
  • 12
  • A great question, which generates different opinions! – ZygD May 30 '15 at 08:08
  • @ZygD Luckily everyone can have his own opinion, so I can say that this question appears as lazy to me. There are a lot of similar questions here on SO (EJP already linked one), it is would be easy to find the answer during research. – Tom May 30 '15 at 09:08
  • @Tom That may be true, but this question combines small things in other questions into one place. That's why I really like it. Concise and clear. – ZygD May 30 '15 at 09:30

2 Answers2

8

Let's look step-by-step:

String s1 = "cat";
String s2 = "cat";

These two will be just the same constant pool entry created in your class file by javac compiler. When this class is loaded, this string (along with all other constant pool strings) will be automatically interned, thus it will be also merged with other "cat" strings in other classes.

String s3 = "c"+"at";

This is practically the same: if string concatenation can be computed during the compilation, it's done by javac. So it's practically the same as s1 and s2. This is covered by JLS, chapter 15.18.1:

The String object is newly created (§12.5) unless the expression is a constant expression (§15.28).

String s4 = new String("cat");

Here you explicitly create a new object. Java language guarantees that when you use a new keyword, you will have a new distinct object which cannot be the same as any of objects created previously. However if you use this object only in current methods (or in methods which can be inlined into the current) and don't use == operation to compare it with other strings, JIT compiler can skip the object allocation for optimization. But if you actually use == or System.identityHashCode, or this method is executed as interpreted frame, then it will be actually new object.

The "cat" string which is passed to the parameter is actually the same object as s1, s2, and s3.

String s5 = "kitty"+"cat";

This is similar to s3: the javac compiler will just create a "kittycat" string during the compilation. Looking into bytecode you cannot even know that there was a concatenation in the source.

String s6 = new String("kittycat");

This is similar to s4: new object is created explicitly. If you try to use s6 == "kittycat" later, you will get false.

String s7 = s5;

Here you just assign a reference to the previously created s5 string, thus no new object is created here.

So the answer is: at most 4 strings will be created, but in some cases it can be optimized down to 2 strings. And the most important: if you try to check how many strings you have from inside the same program (i.e. not using Java agent or analysing memory dump), you will always get four.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
  • 2
    So my answer with 2 that receiced major downting wasnt infact that wrong, as a matter of fact correct for this question :). – John May 30 '15 at 08:27
  • @user3360241: I did not read your answer. Added the last sentence to clarify things. – Tagir Valeev May 30 '15 at 08:36
  • @user3360241 Not at all. Your answer was wrong in several respects. Read this excellent answer again for why. – user207421 May 30 '15 at 08:56
  • @Tagir Valeev : Am not sure if this is correct or not. But in order to concatenate String s3="c"+"at"; Does Compiler be considering "c" and "at" as two seperate string Objects referenced by s3? – Kumar May 30 '15 at 11:21
  • 1
    @Kumar, no, strings `"c"` and `"at"` will not exist at all. There will be only `"cat"` string in the compiled .class file. – Tagir Valeev May 30 '15 at 14:03
0

user3360241 - Your answer seems to be correct... Not sure why it's been down voted without giving any explanation... if you do this the size will be two..

Set<Integer> set = new HashSet<Integer>();

set.add(s1.hashCode());
set.add(s2.hashCode());
set.add(s3.hashCode());
set.add(s4.hashCode());
set.add(s5.hashCode());
set.add(s6.hashCode());
set.add(s7.hashCode());

System.out.println("size :: "+set.size());
TheCodingFrog
  • 3,406
  • 3
  • 21
  • 27