Why are strings immutable in Java?
Strings are immutable in Java: once a String object is created, its value can never change. Methods such as concat(), replace(), and toUpperCase() never modify the original — they return a new object. The class is declared final and its internal value array (a char[] in Java 8, a byte[] since Java 9) is private, final, and never exposed, with no setter methods.
This deliberate design decision enables the string pool, guarantees thread safety, and protects security-sensitive data.
String pool efficiency — identical literals (for example, repeated locator strings in a Selenium framework) share one pooled object; that sharing is only safe because no reference can change the shared value.
Security — strings hold URLs, file paths, usernames, and database connection details; if strings were mutable, a validated value could be swapped afterwards, so immutability closes that attack window.
Thread safety — immutable objects need no synchronization, so strings shared during TestNG parallel execution are automatically safe for every thread to read.
Hashcode caching —
Stringcomputes its hash once on first use and reuses it, making strings fast, reliable keys in structures likeMap<String, WebElement>.Class loading — class names are passed as strings, and immutability guarantees the JVM loads exactly the class that was requested.
Key terms: immutability, string pool, interning, thread safety, hashcode caching,
final,StringBuilder
public class StringImmutabilityDemo {
public static void main(String[] args) {
String url = "https://vibeprep.ai";
String upper = url.toUpperCase(); // returns a NEW object
System.out.println(url); // Output: https://vibeprep.ai (unchanged)
System.out.println(upper); // Output: HTTPS://VIBEPREP.AI
String a = "selenium";
String b = "selenium"; // reuses the pooled object
System.out.println(a == b); // Output: true (same object from string pool)
String c = new String("selenium"); // forces a new object on the heap
System.out.println(a == c); // Output: false (different objects)
System.out.println(a.equals(c)); // Output: true (same content)
}
}The snippet proves immutability: toUpperCase() leaves the original url untouched and returns a brand-new String. It then shows the payoff, the string pool: two identical literals a and b are == because the JVM shares one pooled object, while new String("selenium") always creates a separate heap object even though its literal argument is pooled.
That is why content comparison must always use equals(), not ==, a distinction interviewers frequently probe.
Structure your answer around the four classic reasons: string pool, security, thread safety, and hashcode caching — naming all four signals real depth. Expect follow-ups on concatenating strings in a loop (use StringBuilder) and the difference between String, StringBuilder, and StringBuffer.
A classic mistake is claiming String is immutable because the class is final: final only prevents subclassing, while immutability really comes from the private final internal array that is never exposed and the absence of mutator methods.