Home > Uncategorized > String Literals and String Pool

String Literals and String Pool

The String Pool:
Sun made an optimization that is rather confusing to many new Java programmers called the String Pool. It allows for Strings, which are one of the most used Objects to optimize themselves and save space. An important point to make is that the String Pool only applies to String literals, meaning their value was assigned, not constructed using a String constructor. Let me start off with an example:

public class Main {

public static void main(String[] args) {
String s1 = “abc”;
String s2 = “abc”;

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

}

}
If you run this program, you get this:

s1 = abc
s2 = abc
s1 == s2? true
s1.equals(s2)? true

Most beginners are told to only compare strings using the .equals() method, simply because it is safer for beginners, however, what is confusing about my program above is that the == operator actually said those two were the same memory location too. How is s1 == s2? I clearly defined 2 different variables! An important concept about Java that you may not know is that symbols (variable names) aren’t actually the object that they are defined as. They actually hold a reference to the spot in memory where the actual object is kept. Since Strings are SO commonly used, Strings literals that are the same are given the same address so that it saves memory and doesn’t have to make another. Think about it as if there can only be one of each String in there and anything matching is assigned a reference to that String. However, once all references are gone, then the object is erased. However, once they change, the addresses are different:

public class Main {

public static void main(String[] args) {
String s1 = “abc”;
String s2 = “abc”;

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

s2 += “abc”;

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

}

}

This outputs this:

s1 = abc
s2 = abc
s1 == s2? true
s1.equals(s2)? true
s1 = abc
s2 = abcabc
s1 == s2? false
s1.equals(s2)? false

HOWEVER, if for any reason you want the variables to not occupy the same location in memory, there are two ways to do this. First, you can use the String constructor, since those are not put into the pool:

public class Main {

public static void main(String[] args) {
String s1 = “abc”;
String s2 = new String(“abc”);

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

}

}

This code says that == is false. And just to prove a point, let’s make both of them use constructors:

public class Main {

public static void main(String[] args) {
String s1 = new String(“abc”);
String s2 = new String(“abc”);

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

}

}

That code yields:

s1 = abc
s2 = abc
s1 == s2? false
s1.equals(s2)? true

OR you can assign them in different steps, forcing it to occupy a different address for each addition. (First they are the same, then s1 is moved to another spot to add on the “c” and the same for s2):

public class Main {

public static void main(String[] args) {
String s1 = “ab”;
String s2 = “a”;
s1 += “c”;
s2 += “bc”;

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

}

}

Output:

s1 = abc
s2 = abc
s1 == s2? false
s1.equals(s2)? true

However, there is a way for a literal and a constructor value (assuming value is the same) to == each other. The magic of intern() method of the String class. What this method does is it looks at its value, and if it matches a value ALREADY IN the String pool, it returns a reference to the object in the pool, else it adds itself to the pool. Observe:

public class Main {

public static void main(String[] args) {
String s1 = “abc”;
String s2 = new String(“abc”);
s2 = s2.intern();

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

}

}

This returns:

s1 = abc
s2 = abc
s1 == s2? true
s1.equals(s2)? true

Cool huh? This happens because s1 is ASSIGNED to “abc” and is added to the pool. s2, however, is constructed to “abc”, but not added to the pool. But the intern() method sees that the VALUE “abc” is already in the pool and thus returns the reference to s1. I got a challenge problem for you now. Will s1 == s2 in the following code?

public class Main {

public static void main(String[] args) {
String s1 = new String(“abc”);
String s2 = new String(“abc”);
s2 = s2.intern();

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

}

}

… The answer is no. The intern() method is called, but neither s1 nor s2 is in the pool so all the intern() method does is add it to the pool. To make THESE ==, you must call intern() twice so that there is already a reference in the pool (from the first call).

public class Main {

public static void main(String[] args) {
String s1 = new String(“abc”);
String s2 = new String(“abc”);
s2 = s2.intern();
s1 = s1.intern();

System.out.println(“s1 = ” + s1);
System.out.println(“s2 = ” + s2);
System.out.println(“s1 == s2? ” + (s1 == s2));
System.out.println(“s1.equals(s2)? ” + (s1.equals(s2)));

}

}

This returns:

s1 = abc
s2 = abc
s1 == s2? true
s1.equals(s2)? true

That’s all I have on that for now! I encourage you all to experiment with this, as I’m sure there is SOMETHING that I missed in this huge concept. Happy reading.

Advertisements
Categories: Uncategorized
  1. srinubuddavarapu
    September 5, 2013 at 11:43 AM

    Very Useful Information. Thank you….:)

  2. suhas
    September 17, 2013 at 12:04 AM

    cool

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: