Please enable JavaScript to use CodeHS

Understand the Java String Pool

For many, the Java String Pool remains a slight mystery. In this tutorial, you will take a deeper dive into understanding how the String pool works and when Java uses the String pool versus creating a separate object.

By David Burnham

Introduction

Java strings are often a point of confusion for new students. In Java, String types are actually objects, however, they get created in a similar fashion to primitive variables such as integers, doubles, and characters.

Recall that unlike primitives, objects are created in the heap and the variable holds a reference to that heap object.

Strings, like other objects cannot be compared reliably using ==. With objects, the == compares the reference value, not the actual object value. While the == will sometimes return true when comparing two strings, there are situations when the String values are the same but == will return false.

Why is this? The answer in what you are comparing. == compares the reference values, so if two variables reference different objects, they will not be equal using ==. Before getting into how the String pool works, let’s first take a look at which values actually return true using == versus which return true when using .equals(). Explore the example below. When looking at the example, you will notice that there are two ways to create a new String. The first way is using a String literal without the constructor. The second way is to create a String object using the String constructor.

Did you notice that the two String literals were equal regardless of how they were compared, but when comparing the String literal to the String object, only the .equals() returned true? The answer lies in how Java uses the String Pool.

Java String Pool

The Java String Pool is a special part of memory that is set aside to hold String literals. When a String literal is created, Java looks to the String Pool to see if that literal already exists. If it does, Java uses the existing String Pool object and assigns the variable the same reference. If it does not already exist, java creates a new value in the String pool, which is a process called interning.

This is why you see the two String literals returning true when comparing using ==. Since they have the same reference, == returns true.

But why does the String object not use the same reference? The String Pool only holds true for String literals and when the String constructor is used, a String object is created in the main part of the heap, not in the String Pool. So even though the Strings are the same, a String object will never have the same reference as a String literal.

The example below helps to illustrate this by using the identityHashCode() command. This command returns a hash value that represents the object. If two variables point to the same object, identityHashCode will produce the same hash value.

As you look at the output below, notice which values share the same reference. String literals that are the same will have the same hash values, but each String object will have a different value. None of the String objects will ever match a value of the String literal since they are not part of the String Pool.

To summarize, anytime a String literal is created, Java checks the String Pool. If that literal exists, it will use that object and the new variable will have the same reference as all other variables that are assigned the same String literal. Any other String object will be created in the heap and be a unique object. This includes String values that are created from user input using the Scanner class.

Manually Interning a String

As mentioned above, the process for adding a value to the String Pool is known as interning. Java actually allows you to take a String object and add it to the String Pool manually using the .intern() command. When doing so, the original String still exists in the heap, but a new variable can be assigned the reference value from the String Pool.

Check out this final example below where you will see a String object created using the Scanner class and then that value manually interned. Notice that the manually interned value will match the other String Literal values (assuming you enter Hello at the prompt).