Java String Pool: String Literals vs new String()
Introduction
Programs use the same strings again and again -
(Note - The string pool only works because strings are immutable, as explained in Java String Basics and ImmutabilityClick to read tutorial: Java String Basics and Why Strings Are Immutable.) What is the String pool? The String pool (also called the string constant pool or intern pool) is a table, kept by the JVM, of unique
Every string literal in your code is pooled. When a class is loaded and a literal such as
OUTPUT of the above code
Explanation of the code
Compile-time constants and runtime strings
Which strings end up in the pool? The rule is -
OUTPUT of the above code
This is exactly why comparing strings with
OUTPUT of the above code
How many objects does this create?
A classic interview question asks how many
The answer is up to two -
"OK", "id", "name". Java avoids storing thousands of identical copies with a special area called the String pool. This tutorial explains the Java String pool, and the difference between string literals and new String(). We will start with what the string pool is and how literals use it. We will then see why new String() creates a separate object, and prove both with ==. Next we will look at compile-time constants and strings built at runtime, and move strings into the pool with intern(). Lastly, we will go through what all this means for your code - and the classic interview question of how many objects a line creates.(Note - The string pool only works because strings are immutable, as explained in Java String Basics and ImmutabilityClick to read tutorial: Java String Basics and Why Strings Are Immutable.) What is the String pool? The String pool (also called the string constant pool or intern pool) is a table, kept by the JVM, of unique
String objects. Since Java 7 it lives on the ordinary heap, so pooled strings which are no longer used can be garbage collected.Every string literal in your code is pooled. When a class is loaded and a literal such as
"Java" is first used, the JVM looks in the pool: if a "Java" object is already there, the literal refers to it; if not, a new object is created and added to the pool. So every "Java" literal in the whole program refers to the same object. This is safe only because strings are immutable - no one can change the shared object.
Literals vs new String()
new always creates a new object. So new String("Java") creates a separate String object on the heap, outside the pool, containing a copy of the pooled literal's characters. The == operator, which checks whether two references point to the same object, shows the difference.
String literals share one pooled object
//PoolDemo.java
public class PoolDemo {
public static void main(String[] args) {
String a = "Java";
String b = "Java";
String c = new String("Java");
String d = new String("Java");
System.out.println("a == b : " + (a == b));
System.out.println("a == c : " + (a == c));
System.out.println("c == d : " + (c == d));
System.out.println("a.equals(c) : " + a.equals(c));
System.out.println("same identity (a,b), (a,c): "
+ (System.identityHashCode(a) == System.identityHashCode(b)) + ", "
+ (System.identityHashCode(a) == System.identityHashCode(c)));
}
}
a == b : true a == c : false c == d : false a.equals(c) : true same identity (a,b), (a,c): true, false
aandbcome from the same literal, so they refer to the one pooled object -a == bistrue.canddwere each created withnew, so each is a separate object, different from the pooled one and from each other.equals()compares the characters, soa.equals(c)istrueeven though they are different objects.System.identityHashCode()is based on the object itself, not its contents, which confirms which variables share an object.
- Constant expressions are pooled. When
+joins only literals andfinalconstants, the compiler joins them itself, and the result is a single pooled literal."Ja" + "va"is exactly the same as"Java". - Strings built at runtime are not pooled. Joining a non-final variable, reading input, or calling methods such as
substring()ortoUpperCase()creates a new, unpooled object.
Compile-time constants vs runtime strings
//ConstantsDemo.java
public class ConstantsDemo {
public static void main(String[] args) {
String java = "Java";
String joinedLiterals = "Ja" + "va"; // joined by the compiler
final String ja = "Ja";
String joinedConstant = ja + "va"; // ja is a constant, also joined by the compiler
String part = "Ja";
String joinedAtRuntime = part + "va"; // part is not final: joined at runtime
String fromMethod = "JAVA".toLowerCase().replace('j', 'J');
System.out.println("literal + literal : " + (java == joinedLiterals));
System.out.println("constant + literal : " + (java == joinedConstant));
System.out.println("variable + literal : " + (java == joinedAtRuntime));
System.out.println("from methods : " + (java == fromMethod));
System.out.println("but all are equal : " + (java.equals(joinedAtRuntime) && java.equals(fromMethod)));
}
}
literal + literal : true constant + literal : true variable + literal : false from methods : false but all are equal : true
== is so dangerous - it gives true for some equal strings and false for others, depending on how each string was made.
intern() - adding a string to the pool
intern() returns the pooled copy of a string. If an equal string is already in the pool, that object is returned; otherwise this string is added to the pool and returned.
Using intern()
//InternDemo.java
public class InternDemo {
public static void main(String[] args) {
String pooled = "JavaBrahman";
String built = new StringBuilder("Java").append("Brahman").toString();
System.out.println("pooled == built : " + (pooled == built));
System.out.println("pooled == built.intern() : " + (pooled == built.intern()));
}
}
pooled == built : false pooled == built.intern() : true
intern() can save memory when a program holds very many copies of a small set of strings - for example, millions of records with the same few country names. In everyday code you rarely need it.
String objects this line creates -
The classic interview question
String s = new String("Hello");
- the literal
"Hello", created in the pool when the class is loaded and the literal is first used - unless another"Hello"literal has already put it there; - the new
Stringobject created bynew, whichsrefers to.
- Always compare strings with equals(), never
==. The pool makes==work by accident for literals, which hides the bug until a string comes from input or a calculation. See == vs equals() vs compareTo()Click to read tutorial: Java String Comparison: == vs equals() vs compareTo(). - Use literals, not new String().
new String("...")only creates an unnecessary object. - Do not rely on the pool for correctness - treat it as a memory optimization which the JVM does for you.
new String(), and used == and equals() to show that new always creates a separate object. Next we saw that compile-time constant expressions are pooled while strings built at runtime are not, and used intern() to get a pooled copy. Lastly, we answered the "how many objects" interview question, and went through what the pool means for everyday code. In the next tutorial, we will compare strings properly with equals() and compareTo()Click to read tutorial: Java String Comparison: == vs equals() vs compareTo().Java Fundamentals Tutorials
Java String Basics and Why Strings Are ImmutableClick to read tutorial: Java String Basics and Why Strings Are Immutable Java String Comparison: == vs equals() vs compareTo()Click to read tutorial: Java String Comparison: == vs equals() vs compareTo() Essential Java String Methods with ExamplesClick to read tutorial: Essential Java String Methods with Examples String vs StringBuilder vs StringBuffer in JavaClick to read tutorial: String vs StringBuilder vs StringBuffer in Java Java Text Blocks: Multi-line Strings with ExamplesClick to read tutorial: Java Text Blocks: Multi-line Strings with Examples Common Java String Programs with ExamplesClick to read tutorial: Common Java String Programs with Examples What is Java? History, Features, Editions and UsesClick to read tutorial: What is Java? History, Features, Editions and Uses
Java String Basics and Why Strings Are ImmutableClick to read tutorial: Java String Basics and Why Strings Are Immutable Java String Comparison: == vs equals() vs compareTo()Click to read tutorial: Java String Comparison: == vs equals() vs compareTo() Essential Java String Methods with ExamplesClick to read tutorial: Essential Java String Methods with Examples String vs StringBuilder vs StringBuffer in JavaClick to read tutorial: String vs StringBuilder vs StringBuffer in Java Java Text Blocks: Multi-line Strings with ExamplesClick to read tutorial: Java Text Blocks: Multi-line Strings with Examples Common Java String Programs with ExamplesClick to read tutorial: Common Java String Programs with Examples What is Java? History, Features, Editions and UsesClick to read tutorial: What is Java? History, Features, Editions and Uses