Lesson 8 / 38
Strings: Pool, Builders & Gotchas
Go deeper into how Java strings are stored, why literals get interned in a shared pool, when to use StringBuilder vs StringBuffer, and the classic == vs equals mistake.
The string pool
String literals ("hi") are stored in a special string pool inside the heap. When the compiler sees the same literal twice, both variables point at the same pooled object. new String("hi") deliberately creates a fresh, non-pooled object.
String a = "hi";
String b = "hi";
String c = new String("hi");
System.out.println(a == b); // true (same pooled literal)
System.out.println(a == c); // false (different object)
System.out.println(a == c.intern()); // true (intern() returns pooled copy)StringBuilder vs StringBuffer
Both build up mutable character sequences. StringBuilder is faster and used almost everywhere; StringBuffer is its older, synchronized twin — reach for it only if the same builder is genuinely shared across threads.
StringBuilder sb = new StringBuilder("Java");
sb.append(" rocks").insert(0, ">> ").reverse();
System.out.println(sb); // skcor avaJ >>
System.out.println(sb.length()); // 11== vs equals(), one more time
== compares references, not content — it can look correct with literals only because of pooling, which is exactly what makes the bug sneaky once a new String(...), substring(), or value read from I/O enters the mix. Always use .equals() (or .equalsIgnoreCase()) for content comparison.
Quick check
Quick check: Why can `s1 == s2` be true for two String literals but false after `new String(...)`?
- == always compares content for strings
- Literals are shared from a string pool; new String() forces a fresh object
- It's a JVM bug
- Strings are primitives so == is undefined
Answer
Literals are shared from a string pool; new String() forces a fresh object — Literals are interned into a shared pool, so identical literals share one object. new String(...) opts out of pooling and always allocates a new object on the heap.