Skip to main content

3.1 String Immutability & the String Constant Pool

What is a String in Java?​

A String is a sequence of characters.

String name = "Sarwvidya";

// String stores multiple characters together.
// Internally, modern Java represents String data using a byte[]/compact representation
// when possible, but conceptually we can think of it as a sequence of characters.

Unlike C/C++, Java does not have a separate primitive string type.

String is a class in Java:

String name = "Java";

System.out.println(name.length()); // 4

So:

String
↓
Java class
↓
java.lang.String

You don't need to import it because java.lang is automatically available.

Two ways to create a String​

Method 1: String literal​

String s1 = "Java";

This is the most commonly used way.

Java uses a special memory area called the String Pool for string literals.

Method 2: Using new​

String s2 = new String("Java");

This explicitly creates a new String object.

Important​

String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");

System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1.equals(s3)); // true

Why?

s1 ───────┐
↓
"Java" ← String Pool
↑
s2 ───────┘

s3 ──→ separate String object

== compares references.

equals() compares content.

What is String Pool?​

The String Constant Pool is a special area associated with the JVM's heap where Java maintains canonical String literals.

For example:

String a = "Hello";
String b = "Hello";

Java doesn't need two identical literal objects.

Conceptually:

a ─────┐
↓
"Hello"
↑
b ─────┘

So:

System.out.println(a == b);

prints:

true

This saves memory.

Therefore,

String Pool is a special area in the heap where Java stores and reuses String literals. If the same literal already exists, Java can reuse the existing object instead of creating another one.

Why is String immutable?​

Immutable means: Once a String object is created, its value cannot be changed.

Example:

String s = "Java";
s.concat(" Developer");
System.out.println(s); // Output = Java

Many beginners expect output to be:

Java Developer

But output is:

Java

Because concat() creates a new String.

String s = "Java";
s = s.concat(" Developer");
System.out.println(s); // Java Developer

Now the reference s points to the new String.

Why is String immutable?​

1. String Pool​

Because Strings are reused through the String Pool, changing one String could affect other references.

For example:

String a = "Java";
String b = "Java";

If a could modify "Java" into "Python", then b could unexpectedly see "Python".

Immutability prevents this.

2. Security​

Strings are commonly used for sensitive or important values such as:

File paths
Database URLs
Class names
Network connections
Authentication-related values

If Strings could change after validation, it could create security problems.

3. Thread safety​

Because a String cannot change after creation, multiple threads can safely read the same String without synchronization for the String's own state.

4. HashMap / HashSet​

Strings are frequently used as keys.

Map<String, Integer> map = new HashMap<>();
map.put("Java", 100);

If the String's content could change after it was used as a key, its hash code could change and the object could become difficult to locate in the map.

5. == vs equals()​

== - Checks whether two references point to the same object.

equals() - Checks whether two Strings have the same content.

String a = new String("Java");
String b = new String("Java");

System.out.println(a == b); // false
System.out.println(a.equals(b)); // true

Because:

a ──→ Object 1: "Java"

b ──→ Object 2: "Java"

Different objects, same content.

What happens with +?​

Consider:

String s = "Java";
s = s + " Developer";

Because String is immutable, Java creates a new String.

Conceptually:

"Java"
+
" Developer"
↓
"Java Developer"

The old "Java" object isn't modified.

For a small number of concatenations, this is fine. But repeatedly doing this can create unnecessary temporary Strings.

Example of String Constant Pool Memory Model​

String s1 = "Java"; // Allocated in String Constant Pool
String s2 = "Java"; // Reuses the identical pool reference!
String s3 = new String("Java"); // Creates a separate Object in general Heap!
JVM Heap Space
┌───────────────────────────────────────────────────────────┐
│ String Constant Pool (SCP) │
│ ┌─────────────────────────────────┐ │
│ │ "Java" (Address: @0x100) │◄─── s1 & s2 │
│ └─────────────────────────────────┘ │
│ │
│ General Heap │
│ ┌─────────────────────────────────┐ │
│ │ new String instance (@0x200) │◄─── s3 │
│ │ (internal char/byte[] -> @0x100)│ │
│ └─────────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘

Resulting checks:

System.out.println(s1 == s2); // true (Same pool address)
System.out.println(s1 == s3); // false (Different heap address)
System.out.println(s1.equals(s3)); // true (Identical content)