5

I'm trying to understand how the String pool works and what are the rules for a string to be equal to another String.

For example this snippet :

public static void main(String[] hi){
    String s1 = "lol";
    String s2 = "lol";
    String s3 = new String("lol");
    System.out.println( s1 == s2 );// true
    System.out.println( s2 == s3); // false
    s3.intern(); //line 1
    System.out.println( s1 == s3); // false
    testString(s1);

}

private static void testString(String s1){
    String s4 = "lol";
    System.out.println( s1 == s4); // true
}
  1. At //line 1: the string is added to the string pool. Since it's not equal to s1 I assume there is a duplicate in the string pool. Correct ?

  2. What is the rule for having a duplicate in the pool ? In other words when does someString == someString return false even though both string have the same char sequence ?

PS: I use string1.equals(string2) everywhere no matter what. I just want a deeper understanding of the underlying mechanism.

Ced
  • 15,847
  • 14
  • 87
  • 146
  • 1
    the result of `s3.intern("lol")` should be a reference to the same instance as the string constants. – Hank D Jun 08 '16 at 06:54
  • Also http://stackoverflow.com/questions/14150628/string-constant-pool-java and http://stackoverflow.com/questions/1552301/immutability-of-strings-in-java – Tunaki Jun 08 '16 at 06:59

5 Answers5

5

Your s3.intern(); should be s3 = s3.intern(); to get the correct behaviour.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
3
  1. At //line 1: the string is added to the string pool. Since it's not equal to s1 I assume there is a duplicate in the string pool. Correct ?

No, not correct. There is already a string "lol" in the string pool, so it's not going to create a duplicate. However, you are not doing anything with the return value of the call to intern() so s3 is still referring to the String object that is not in the pool.

Try s3 = s3.intern(); instead of just s3.intern();

  1. What is the rule for having a duplicate in the pool ? In other words when does someString == someString return false even though both string have the same char sequence ?

The whole point of the String pool is to avoid duplicate strings in memory, so there will not be any duplicates in the String pool.

Jesper
  • 202,709
  • 46
  • 318
  • 350
  • Ok but concerning point n2. s1 == s2 evaluate to true no matter where those two are created then ? Assuming they were both originally instantiated as such : `myString = "lol";` – Ced Jun 08 '16 at 07:05
  • 1
    When you do `String myString = "lol";` you are not directly instantiating a new `String` object. The compiler is smart enough to make `myString` refer to the `String` that's already in the pool, avoiding creating a new `String` object. – Jesper Jun 08 '16 at 07:08
  • alright, I was just wondering if the behavior would be different if for example there were jars imported or things like that. Ultimately that's not really important, I get the gist. – Ced Jun 08 '16 at 07:10
2

There is difference when comparing string literals which are always taken from the pool (case s1 and s2) with comparing string literal or string created on runtime with constructor to another string created with new.

String literal is guaranteed to be taken from string pool when exact same literal already exists. String object still internally uses string from the pool, but as an object has different reference.

String#intern(); returns reference to string from pool, that is internally used.

Code snippet to show this behavior:

String literalOne = "abc";
String literalTwo = "abc";
String stringOne = new String("abc");
String stringTwo = new String("abc");

System.out.println("literalOne == literalTwo ? " + (literalOne == literalTwo));
System.out.println("stringOne == stringTwo ? " + (stringOne == stringTwo));
System.out.println("Internally stringOne == stringTwo ? " + (stringOne.intern() == stringTwo.intern()));
System.out.println("Internally stringOne == literalOne ? " + (stringOne.intern() == literalOne));

And the output:

literalOne == literalTwo ? true
stringOne == stringTwo ? false
Internally stringOne == stringTwo ? true
Internally stringOne == literalOne ? true
zubergu
  • 3,646
  • 3
  • 25
  • 38
2

basically we can create Sting by two waysbasically we can create Sting by two ways

String str="some data" (not bound to any object like primitive data type)
String strTwo=new String("some String"); (here strTwo object contains value)

As the name suggests, String Pool is a pool of Strings stored in Java HeapMemory. We know that String is special class in java and we can create String object using new operator as well as providing values in double quotes.

String Pool is possible only because String is immutable in Java and it’s implementation of String interning concept. String pool is also example of Flyweight design pattern.

String pool helps in saving a lot of space for Java Runtime although it takes more time to create the String.

When we use double quotes to create a String, it first looks for String with same value in the String pool, if found it just returns the reference else it creates a new String in the pool and then returns the reference.

However using new operator, we force String class to create a new String object and then we can use intern() method to put it into the pool or refer to other String object from pool having same value.

as

public void method(){
String s1 = "Cat";
        String s2 = "Cat";
        String s3 = new String("Cat");

        System.out.println("s1 == s2 :"+(s1==s2));
        System.out.println("s1 == s3 :"+(s1==s3));
}

and output

[![s1 == s2 :true
s1 == s3 :false
bananas
  • 1,176
  • 2
  • 19
  • 39
1

== compares references, so when you try s1 == s3 you are checking to see if these two references point to the same object which is not true since you have created s3 as a new object(new String("lol")).So now the string pool has two different objects that happen to have the same string value("lol") and in your code you have s1,s2,s4 pointing to one and s3 pointing to the other.

In order for you to compare the values of each object that is been referenced you must use equals() method.

theVoid
  • 743
  • 4
  • 14