Skip to content

Here is your structured, compressed, and high-yield technical handbook for Senior Java Interview Series β€” Part 5: Advanced String Interview Questions (50+ Questions) formatted strictly using our locked-in Style 1 (Flowchart-Style ASCII / Box Blocks), tables, and explicit decision flows.


Table of ContentsΒΆ

  1. Core String Concept Questions
  2. String Pool and Intern Questions
  3. StringBuilder and StringBuffer Questions
  4. JVM Internal Questions
  5. Garbage Collection and Memory Questions
  6. Scenario-Based Senior Questions
  7. Coding Questions
  8. Tricky Interview Questions
  9. Quick Revision

1. Core String Concept QuestionsΒΆ

Q1. Why is String immutable in Java?ΒΆ

Immutability guarantees that once constructed, state cannot mutate.

1. Security ParametersΒΆ

  • Prevents mid-execution mutation of sensitive values (e.g., DB URLs, file paths, class loading targets).
url = "jdbc:mysql://localhost/bank"
 β”œβ”€ [Immutable] ──> Value remains fixed across connection lifetime
 └─ [Mutable Risk] ──> Thread 2 could alter host mid-handshake to attacker domain

2. String Pool ReuseΒΆ

  • Enables global instance sharing across the JVM without state corruption.

3. Inherent Lock-Free Thread SafetyΒΆ

  • Multi-threaded read access requires zero synchronization overhead.

4. $O(1)$ HashCode CachingΒΆ

  • Immutable state enables memoizing computed hash values inside private int hash.

Follow-up: Why does declaring the class final support immutability? final prevents subclassing. Without final, a malicious subclass could override mutators/accessors, introduce mutable fields, and break immutability guarantees.


Q2. Is String really 100% immutable?ΒΆ

  • API Perspective: Yes. Public APIs expose zero mutator methods.
  • JVM/Reflection Perspective: Historically, reflection could mutate private final char[] value. Modern JDKs (Java 9+ Module System) encapsulate java.lang internals, blocking reflection mutation unless explicitly forced via deep JVM args.

Q3. Difference between String Object and String Constant Pool?ΒΆ

Feature String Object (Heap) String Constant Pool (SCP)
Storage Location General Heap memory Dedicated hash table inside Heap
Instantiation Explicit via new String() Implicit via Literals ("") or intern()
Deduplication Distinct duplicate instances allowed Holds single canonical instance per literal

Q4. How many objects are created by String s = new String("Java")?ΒΆ

new String("Java") Allocation
 β”œβ”€ ["Java" Absent from SCP] ──> Creates 2 objects (1 in SCP + 1 on Heap)
 └─ ["Java" Present in SCP]  ──> Creates 1 object (1 on Heap)

Q5. How many objects are created by String s1 = "Java"; String s2 = "Java";?ΒΆ

Literal Execution Flow
 β”œβ”€ [s1 = "Java"] ──> Creates 1 object in SCP
 └─ [s2 = "Java"] ──> Reuses existing SCP object (0 new objects)
  • Total Objects Created: 1 (Both references point to identical SCP memory address).

Q6. Difference between == and equals()?ΒΆ

String Comparison Check
 β”œβ”€ [operator ==]     ──> Reference Equality Check (Compares memory addresses)
 └─ [method equals()] ──> Content Equality Check (Compares character sequences)

ExampleΒΆ

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

System.out.println(a == b);      // false (Distinct Heap instances)
System.out.println(a.equals(b)); // true  (Matching character content)

Q7. Why is String an ideal HashMap key?ΒΆ

  1. Immutable State: Hash code remains stable across life cycle.
  2. Cached Hash Code: hashCode() is calculated once and memoized.
  3. Thread Safety: Lock-free key operations across concurrent threads.

Q8. What happens internally when calling String.concat()?ΒΆ

s = "Java".concat("8")
 β”œβ”€ Step 1 ──> Reads "Java" length (4) & "8" length (1)
 β”œβ”€ Step 2 ──> Allocates new array buffer of size 5
 β”œβ”€ Step 3 ──> Copies characters into new buffer
 └─ Step 4 ──> Instantiates & returns brand-new String object
  • The original "Java" string remains completely untouched in memory.

Q9. Why does String use HashCode Caching?ΒΆ

HashMap lookups recalculate hashCode() per call. Computing polynomial hashes for long strings is expensive ($O(N)$). String caches its computed value in hash on first invocation, enabling $O(1)$ fast lookups thereafter.


2. String Pool and Intern QuestionsΒΆ

Q10. What is String.intern()?ΒΆ

Returns the canonical reference from the SCP.

s1 = new String("Java"); s2 = s1.intern();
 β”œβ”€ ["Java" in SCP]     ──> Returns existing pooled reference to s2
 └─ ["Java" Not in SCP] ──> Adds s1 string to SCP + returns reference

Q11. Difference between String Pool and intern()?ΒΆ

Attribute String Constant Pool (SCP) intern() Method
Type Memory structure inside Heap Instance method on String class
Management JVM automatic management Developer invoked explicitly
Purpose Stores canonical literal instances Retrieves or registers dynamic instances into SCP

Q12. Should you always call intern() on dynamic inputs?ΒΆ

  • No. Interning high-cardinality, unbounded runtime data (e.g., UUIDs, customer names) causes String Pool table bucket collisions and memory explosion.
  • Rule: Intern strictly on finite, low-cardinality values (e.g., country codes "US", "IN", status codes "ACTIVE", "SUCCESS").

Q13. Where is the String Constant Pool stored across Java versions?ΒΆ

SCP Storage Location
 β”œβ”€ [Java 6 and earlier] ──> Stored in PermGen (Fixed size, high OOM risk)
 └─ [Java 7+]            ──> Stored in Main Heap (Dynamically sized, GC-managed)

Q14. Why was the String Constant Pool moved from PermGen to Heap in Java 7?ΒΆ

  • PermGen had fixed size constraints, leading to java.lang.OutOfMemoryError: PermGen space.
  • Moving SCP to Heap allows strings to be collected during standard GC sweeps and dynamically scaled.

Q15. Can String Pool objects be garbage collected?ΒΆ

  • Yes. From Java 7+, pooled strings without active strong references are eligible for collection during GC sweeps.

3. StringBuilder and StringBuffer QuestionsΒΆ

Q16. Why do we need StringBuilder?ΒΆ

String immutability causes loop concatenation anti-patterns (s += i) to allocate thousands of short-lived intermediate Heap objects. StringBuilder mutates an internal buffer without intermediate allocations.


Q17. Difference between StringBuilder and StringBuffer?ΒΆ

Feature StringBuilder StringBuffer
Mutability Mutable Mutable
Thread Safety Not Thread-Safe Thread-Safe
Synchronization Unsynchronized (Fast) Synchronized methods (Slow)
Introduced In Java 5 Java 1.0
Primary Scope Local method variables Shared multi-threaded mutation

Q18. Why is StringBuilder faster than StringBuffer?ΒΆ

Append Execution Flow
 β”œβ”€ [StringBuilder] ──> Direct array modification (Zero locking cost)
 └─ [StringBuffer]  ──> Acquire Monitor Lock ──> Modify array ──> Release Lock

Q19. Is StringBuilder thread-safe?ΒΆ

  • No. Simultaneous concurrent modifications by multiple threads corrupt internal count pointers and array elements, resulting in corrupted output or ArrayIndexOutOfBoundsException.

Q20. Is StringBuffer completely thread-safe in all scenarios?ΒΆ

  • Individual method calls (e.g., .append()) are atomic and thread-safe.
  • Compound checks (e.g., if (sb.length() > 0) sb.deleteCharAt(0);) remain vulnerable to race conditions unless protected by client-side synchronization locks.

Q21. What is the default initial capacity of StringBuilder?ΒΆ

  • Default Empty Constructor (new StringBuilder()): 16 characters.
  • String Constructor (new StringBuilder("Java")): str.length() + 16 ($4 + 16 = 20$).

Q22. How does StringBuilder dynamically increase capacity?ΒΆ

Capacity Exceeded Rule
 β”œβ”€ Standard Formula ──> newCapacity = (oldCapacity * 2) + 2
 └─ Insufficient Formula ──> newCapacity = minimumRequiredCapacity

Q23. Does StringBuilder.append() allocate new objects?ΒΆ

  • Normally No: Modifies elements directly inside the existing array.
  • Exception: When capacity is exceeded, it allocates a new larger array and executes System.arraycopy().

4. JVM Internal QuestionsΒΆ

Q24. Difference between Java 8 and Java 9 String implementations?ΒΆ

Internal Storage Shift
 β”œβ”€ [Java 8]  ──> char[] value (2 bytes / 16 bits per character unconditionally)
 └─ [Java 9+] ──> byte[] value + byte coder flag (Compact Strings optimization)

Q25. What are Compact Strings (JEP 254)?ΒΆ

Introduced in Java 9 to reduce string memory footprint. Since most application strings contain LATIN-1 characters requiring only 1 byte, storing them in 2-byte char[] arrays wasted 50% memory.


Q26. What is the coder field in Java 9+ String?ΒΆ

A byte field indicating array encoding:

coder Encoding Selection
 β”œβ”€ [LATIN1 (0)] ──> Single-byte encoding (ISO-8859-1 / ASCII)
 └─ [UTF16 (1)]  ──> Double-byte encoding (Unicode / Non-ASCII)

Q27. Why was char[] replaced with byte[]?ΒΆ

  1. Cuts string heap memory usage by up to 50% for LATIN-1 strings.
  2. Improves CPU cache-line efficiency due to higher data density.

Q28. How does String.equals() work internally?ΒΆ

s1.equals(s2) Execution Pipeline
 β”œβ”€ [Same Identity (this == obj)] ──> Return true instantly (O(1))
 β”œβ”€ [Type / Length Mismatch]     ──> Return false instantly (O(1))
 └─ [Matching Lengths]           ──> Compare byte[]/char[] elements value-by-value (O(N))

Q29. How does String.hashCode() calculate its value?ΒΆ

Formula:

$$h = \sum_{i=0}^{n-1} s[i] \cdot 31^{n-1-i}$$


Q30. Why use prime multiplier 31 in hash calculations?ΒΆ

  1. Prime Number Properties: Distributes hash codes evenly across table buckets, reducing collisions.
  2. CPU Optimization: $31 \cdot i$ is optimized by compiler to bitwise shifts and subtractions: (i << 5) - i.

5. Garbage Collection and Memory QuestionsΒΆ

Q31. What is G1 GC String Deduplication?ΒΆ

A feature (-XX:+UseStringDeduplication) available with G1 GC. During GC sweeps, it identifies distinct Heap String instances containing identical character arrays and repoints both to a single shared byte[] array, collecting duplicate arrays.


Q32. Difference between String Constant Pool and G1 String Deduplication?ΒΆ

Metric String Constant Pool (SCP) G1 String Deduplication
Scope Compile-time literals & intern() calls Dynamic runtime Heap String instances
Timing Instantaneous upon creation/intern Asynchronous during GC cycles
Target Deduplicates String reference objects Deduplicates underlying array storage (byte[])

Q33. When should G1 String Deduplication be enabled?ΒΆ

  • Recommended: Memory-heavy applications containing large numbers of duplicate strings (e.g., repeated JSON payloads, cache structures).
  • Not Recommended: Applications where strings are highly unique (e.g., cryptographically generated tokens, GUIDs), as inspection adds GC overhead without memory savings.

6. Scenario-Based Senior QuestionsΒΆ

Q34. Production JVM exhibits high memory usage dominated by String objects. How do you debug?ΒΆ

Production Debugging Pipeline
 β”œβ”€ Step 1 ──> Capture Heap Dump (jmap / gcmd)
 β”œβ”€ Step 2 ──> Analyze using Eclipse MAT or VisualVM (Inspect Dominator Tree & Duplicate Strings)
 β”œβ”€ Step 3 ──> Identify source (e.g., unbounded interning, loop concatenation, duplicated JSONs)
 └─ Step 4 ──> Apply fix (Refactor to StringBuilder, apply bounded caching, or enable G1 String Deduplication)

Q35. Performance degrades during large payload generation (response += data). What is the issue and fix?ΒΆ

  • Root Cause: Re-allocates intermediate String objects continuously inside the loop, overloading GC.
  • Fix: Replace String concatenation with StringBuilder initialized with an estimated capacity: new StringBuilder(estimatedSize).

Q36. Should database primary key strings be interned using .intern()?ΒΆ

  • No. Primary keys/UUIDs are high-cardinality, dynamic values. Interning millions of unique keys floods the String Pool table, causing bucket collisions and degraded performance.

Q37. A developer uses StringBuffer inside local method scopes. Should you approve?ΒΆ

  • No. Local method variables are confined to a single thread's stack frame. Using StringBuffer adds unnecessary monitor locking overhead. Replace with StringBuilder.

Q38. API latency increased after switching from StringBuilder to StringBuffer. Why?ΒΆ

  • StringBuffer enforces monitor lock acquisition/release overhead on every method invocation, adding CPU synchronization latency.

Q39. Why are immutable strings preferred in distributed microservices?ΒΆ

  1. Thread Safety: Lock-free concurrent sharing across worker threads.
  2. Key Stability: Immutable keys prevent cache corruption in distributed stores (e.g., Redis).
  3. Security Integrity: Guaranteed parameter stability across async execution pipelines.

7. Coding QuestionsΒΆ

Q40. What is the output of the following code?ΒΆ

String a = "Java";
String b = "Ja" + "va";
System.out.println(a == b);
  • Output: true
  • Reason: Compile-time constant folding evaluates "Ja" + "va" directly to "Java", referencing the identical SCP instance.

Q41. What is the output of the following code?ΒΆ

String a = "Java";
String b = "Ja";
String c = b + "va";
System.out.println(a == c);
  • Output: false
  • Reason: b is a variable, so concatenation occurs dynamically at runtime, creating a new Heap object.

Q42. Optimize the following string accumulation logic:ΒΆ

// Anti-Pattern
String result = "";
for (String value : list) {
    result = result + value;
}

Optimized CodeΒΆ

StringBuilder sb = new StringBuilder();
for (String value : list) {
    sb.append(value);
}
String result = sb.toString();

Q43. Reverse a String using built-in utilities:ΒΆ

public class StringUtil {
    public static String reverse(String input) {
        if (input == null) return null;
        return new StringBuilder(input).reverse().toString();
    }
}

8. Tricky Interview QuestionsΒΆ

Q44. Is String immutable because the class is declared final?ΒΆ

  • No. final on the class level only prevents subclassing. Immutability is enforced because:
  • Internal storage array value is private and final.
  • No mutator methods are exposed.
  • Defensive copying is used where applicable.

Q45. Can a final String field be modified using Reflection?ΒΆ

  • In legacy Java versions (Java 8 and earlier), reflection could modify private final fields. From Java 9+ onward, the Module System restricts deep reflection access to java.lang internals. Modifying immutable strings breaks JVM assumptions and leads to unpredictable bugs.

Q46. Is StringBuilder immutable?ΒΆ

  • No. StringBuilder is mutable; its contents mutate directly inside its internal character array.

Q47. Does string concatenation (+) always instantiate a StringBuilder?ΒΆ

String Concatenation Strategy
 β”œβ”€ [Compile-Time Constants ("a" + "b")] ──> Constant Folding (No StringBuilder allocated)
 β”œβ”€ [Dynamic Variables (Java 8)]         ──> Compiler injects new StringBuilder()
 └─ [Dynamic Variables (Java 9+)]        ──> Invokes StringConcatFactory (invokedynamic optimization)

Q48. How did string concatenation change in Java 9+?ΒΆ

Java 9 replaced static StringBuilder bytecode generation for concatenation with invokedynamic calling StringConcatFactory.makeConcatWithConstants(). This allows the JVM to change concatenation strategies without recompiling bytecode.


Q49. Why is String immutable while StringBuilder is mutable?ΒΆ

  • String: Designed for thread safety, global instance sharing, domain security, and key stability in hash tables.
  • StringBuilder: Designed purely as a high-performance buffer for local string manipulation.

Q50. How do you implement a custom Immutable Class in Java?ΒΆ

  1. Declare the class as final (prevents subclassing).
  2. Declare all fields as private and final.
  3. Initialize all fields via constructor (no setters).
  4. Perform defensive copying for any mutable object inputs and outputs.

Quick RevisionΒΆ

  • Immutability Drivers: Security, SCP sharing, thread safety, cached hash codes.
  • SCP Location: PermGen (Java 6) $\rightarrow$ Main Heap (Java 7+).
  • Compact Strings (Java 9+): Swapped char[] for byte[] plus coder flag (0 for LATIN-1, 1 for UTF-16), saving 50% memory.
  • == vs .equals(): == compares reference addresses; .equals() compares character values.
  • intern() Rule: Returns canonical SCP reference. Use on finite low-cardinality values only.
  • StringBuilder vs StringBuffer: StringBuilder is unsynchronized (fast); StringBuffer is synchronized (slow).
  • G1 String Deduplication: Asynchronously merges duplicate byte[] arrays on Heap during GC sweeps (-XX:+UseStringDeduplication).
  • Java 9 Concatenation: Uses invokedynamic via StringConcatFactory instead of hardcoded StringBuilder instantiations.