4. Strings & String Pool

String Immutability, String Constant Pool & Mutability

Deep dive into Java String immutability mechanics, String Constant Pool (SCP) memory allocation, intern(), StringBuilder vs StringBuffer performance, and Text Blocks.

🖨️ String Immutability & The String Constant Pool (SCP)

In Java, instances of java.lang.String are strictly immutable. Once created, their sequence of character bytes cannot be altered in memory.

  • Analogy: A Currency Printing Press Vault.
    • Immutable String: A printed $100 bill. You cannot erase the ink on a $100 bill and turn it into a $500 bill. To get $500, the mint must print an entirely new currency bill.
    • String Constant Pool (SCP): A special high-security vault inside Heap memory. Before printing a new bill ("Hello"), the mint checks if an identical bill already exists in the vault. If found, it reuses the existing bill reference, saving memory!
                  String Constant Pool (SCP) Heap Allocation

    String s1 = "Java";  ──┐
                           ├─► [ String Constant Pool (SCP) ] ──► "Java" (Single Instance)
    String s2 = "Java";  ──┘
    
    String s3 = new String("Java"); ──► Heap Memory Object ──► Points to "Java" in SCP

🛠️ Instantiation Mechanics: Literal vs. new Keyword

public class StringPoolDemo {
    public static void main(String[] args) {
        // 1. String Literal: Creates 1 object in SCP (or reuses existing)
        String s1 = "Hello";
        String s2 = "Hello";
        System.out.println(s1 == s2); // TRUE (Both point to the SAME object in SCP!)

        // 2. New Keyword: Creates 2 objects (1 in Heap, 1 in SCP if not present)
        String s3 = new String("Hello");
        System.out.println(s1 == s3); // FALSE (s3 points to explicit Heap object!)

        // 3. String.intern(): Returns canonical reference from SCP
        String s4 = s3.intern();
        System.out.println(s1 == s4); // TRUE (intern() fetches reference from SCP!)
    }
}

StringBuilder vs. StringBuffer vs. String

Concatenating strings inside loops using + creates thousands of short-lived temporary String objects in memory, degrading Garbage Collection performance:

// ❌ ANTI-PATTERN: Creates 10,000 temporary String objects on Heap!
String result = "";
for (int i = 0; i < 10000; i++) {
    result += i; // Instantiates new StringBuilder and new String every iteration!
}
Metricjava.lang.Stringjava.lang.StringBuilderjava.lang.StringBuffer
MutabilityImmutable (Fixed array)Mutable (Expandable array)Mutable (Expandable array)
Thread SafetyThread-Safe (Immutable)Not Thread-SafeThread-Safe (Synchronized)
Performance SpeedSlow for concatenation loopsExtremely Fast (Single-thread)Slightly Slower (Lock overhead)
Storage AllocationSCP / HeapHeap RAM BufferHeap RAM Buffer
// ✅ BEST PRACTICE: Use StringBuilder for dynamic string assembly
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append(i);
}
String result = sb.toString();

📜 Java 15+ Multiline Text Blocks (""")

Java 15 introduced multiline Text Blocks delimited by triple quotes ("""), eliminating escape sequences for JSON, SQL, and HTML strings:

public class TextBlockDemo {
    public static void main(String[] args) {
        // Modern clean multiline JSON string
        String jsonPayload = """
                {
                    "name": "Alice",
                    "role": "Lead Architect",
                    "active": true
                }
                """;
        System.out.println(jsonPayload);
    }
}

❓ Conceptual Quizzes

Knowledge Check

What happens in memory when executing: String s1 = 'Java'; String s2 = new String('Java');?

Knowledge Check

Why is StringBuilder preferred over StringBuffer in single-threaded application code?


💻 Practice Problems

Problem: High-Speed Log Message Formatter

Write a method public static String buildLogHeader(String level, String module, String message) that formats a log string using StringBuilder to avoid intermediate object allocations.

On this page