-1
String Str1= new String("java");  
String Str3 = new String("java");

System.out.println(Str1==Str3);

The 1st line of code creates object str1 with content "java" init both in String pool and heap. Now what will Str3 does? I know it create Str3 in heap what about Str3 in String pool? What does 3rd line do? does it checks for equality in String pool or in heap area? I know that it gives false but my question is if Str1 and Str3 are stored in String pool == should give true right as references are same.

ravi
  • 15
  • 1
  • 1
    You are creating `Str3` as a **new** object. Since `==` checks for references, you'll get `false`. – Maroun May 07 '17 at 08:29
  • Possible duplicate of [How do I compare strings in Java?](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) – Joe C May 07 '17 at 08:30
  • I know that it will give false. My question here is if both str1 and str2 are stored in String pool == should give true. – ravi May 07 '17 at 08:32
  • 1
    "*if both str1 and str2 are stored in String pool == should give true*" yes, but this is not your case. You are explicitly creating two separate strings with same text (and one string literal `"java"` which will be present in pool). Even if there was no such string in pool you can place only one of them there, interning second one will have no effect, you will get as result of `intern()` string previously inserted. – Pshemo May 07 '17 at 08:42
  • The point is `Str1` and `Str3` are **not** stored in the String pool. Objects created with `new`, even Strings, are never in the String pool. – Kevin Anderson May 07 '17 at 08:46
  • `new` *always* creates a new instance (or it fails with an exception). So `new Anything(...) == new Anything(...)` is always false (or it fails with an exception). – Andy Turner May 07 '17 at 08:48
  • @KevinAnderson "Objects created with new, even Strings, are never in the String pool" I wouldn't say never since we can place it there explicitly by `intern()` method. You probably meant something like "not stored in String pool automatically". – Pshemo May 07 '17 at 08:50
  • @Pshemo no I meant "never in the String pool". In short, using OP's examples: `Str1 != Str1.intern()` will always be true immediately after `String Str1 = new String("java");` – Kevin Anderson May 07 '17 at 09:30

1 Answers1

2

The 1st line of code creates object str1 with content "java" init both in String pool and heap.

Actually:

  1. The string pool is part of the heap. (This doesn't actually relate to your misconception, but it helps to get these things straight in your head.)
  2. The string object corresponding to the "java" literal is created by the classloader, not by that statement. It is created when the class is loaded1 ... not when the code is run.

So, in fact that statement only creates a string object in the heap.

Now what will Str3 does?

The second statement creates a single string object ... in the heap.

As per the above explanation, the string object for the "java" literal used in this statement was created previously. (Indeed, if you look in the bytecode file, you will see that there is only one "java" string in the file's constant pool. So, the classloader won't even need to create two string instances and intern() both of them. Only one is created and interned.)

I know it create Str3 in heap what about Str3 in String pool?

Nope. All string literals are created in the string pool, which automatically dedups them.

What does 3rd line do? Does it checks for equality in String pool or in heap area?

Nope. It tests to see if the object references are the same; i.e. if they are the same object. It doesn't actually test where they are in.

(You can't actually directly test if a String is in the pool or not. And you can't even test if an object is in the heap or not ... if the JVM provides you a way to allocate objects outside of the (regular) heap.)

I know that it gives false but my question is if Str1 and Str3 are stored in String pool == should give true right as references are same.

They aren't in the string pool. They are ordinary heap objects.

Think of it this way, the fact that == returns false proves that they aren't (both) in the string pool. Because if they were both in the string pool they would have to be the same String object.


Here is what the JLS says on string literals and identity:

"Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern."

This interning happens when the class is loaded1.


1 - The specs don't say when the interning happens. It appears that recent JVMs resolve a method's reference to a String literal lazily; i.e. the interning happens the first time the method is called by the bytecode interpreter. However, this doesn't change the substance of the above explanation.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • It actually seems like the string corresponding to the literal is created and interned when its referenced for the first time. (If you call System.identityHashCode(" j".concat("ava ").intern()) and System#gc several times prior using the literal, it will print different hashcodes, after using the literal it will always print the same hashcode). – Nevay May 07 '17 at 09:15
  • @Nevay it has nothing to do with 'before' and 'after'. If you use the entire literal *at all*, *anywhere* in the text of the class, or any other loaded class, it will already exist in the string pool prior to execution. – user207421 May 07 '17 at 09:51
  • @EJP How do you explain this result then? https://ideone.com/204QnH In my opinion it shows pretty clearly that the constant pool of the class does not hold a reference to a string in the string pool until the literal is used for the first time. – Nevay May 07 '17 at 12:08
  • 1
    @Nevay - You are right. I think I found the place where it happens in the bytecode interpreter. (In the code that interprets an LDC bytecode, there is a test to see if the constant reference has been resolved, and code to resolve it if it hasn't been.) I also tried your test in a Java 6 JVM and the behavior is the same there. – Stephen C May 07 '17 at 15:14