# Strings: Pool, Builders & Gotchas — Core Java

Source: https://www.geekswithgeeks.com/en/core-java/java-string-deep-dive

> 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.

```java
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.

```java
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

**Quiz:** Why can `s1 == s2` be true for two String literals but false after `new String(...)`?

- [ ] == always compares content for strings
- [x] 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.
