Why intern() does not work with literal 'java'?

Abhishek Kumar :

I have tried below code:

public class TestIntern {
  public static void main(String[] args) {
   char[] c1={'a','b','h','i'};
   String s1 = new String(c1);
   s1.intern();
   String s2="abhi";
   System.out.println(s1==s2);//true

   char[] c2={'j','a','v','a'};
   String sj1 = new String(c2);
   sj1.intern();
   String sj2="java";
   System.out.println(sj1==sj2);//false

   char[] c3={'J','A','V','A'};
   String tj1 = new String(c3);
   tj1.intern();
   String tj2="JAVA";
   System.out.println(tj1==tj2);//true
  }
}

I have tried many different literals.

Could anyone please explain why intern() doesn't work as expected with literal "java"? Why do the above reference comparisons evaluate to true, except when the literal is "java"?

Petr Janeček :

When the JVM first encounters the new String(new char[] {'a', 'b', 'h', 'i'}) string and you call intern() on it, the reference you just created becomes the canonical one and is stored in the string constant pool. Then "abhi" is pulled out from the constant pool - your canonical instance has been reused.

Your problem is that the literal "java" exists in the constant string pool before the start of your program - the JVM simply has it there for some use. Therefore, calling intern() on new String(new char[] {'j', 'a', 'v', 'a'}) does not intern your reference. Instead, it returns the pre-existing canonical value from the constant pool, and you happily ignore the return value.

You should not ignore the return value, but use it. You never know whether your "definitely original" string has not been living in the constant pool since the start of the JVM. Anyway, all of this is implementation dependent, you should either always use the references returned by the intern() method, or never. Do not mix between them.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=434730&siteId=1