1. What is the String class in Java, and why is it immutable?
Answer:
The String class in Java is a final class in the java.lang package that represents a sequence of
characters. It is one of the most widely used classes in Java, and its immutability is a key design
feature.
Immutability of String:
A String object, once created, cannot be modified. Any operation that appears to modify a String
(e.g., concat(), replace(), toUpperCase()) actually creates a new String object, leaving the original
unchanged.
Immutability is achieved by:
- The String class being declared as final, preventing subclassing.
- The internal character array (private final char[] value) being final, meaning it cannot be reassigned
after initialization.
- No methods in the String class that modify the internal state of the object.
Reasons for Immutability:
- Thread Safety: Immutable objects are inherently thread-safe, as their state cannot be changed by
multiple threads. This eliminates the need for synchronization in multi-threaded environments.
- Security: Immutability ensures that sensitive data (e.g., passwords, file paths) cannot be altered
once created, which is critical in security-sensitive applications.
- String Pool Efficiency: Immutability enables the use of the String pool (a special area in the heap
memory) to cache and reuse String literals, reducing memory overhead.
- Hash Code Caching: Since a String object's state cannot change, its hash code can be cached
(stored in a private field) and reused, improving performance in hash-based collections like
HashMap and HashSet.
Example of Immutability:
String str = "Hello";
str.concat(" World"); // Creates a new String object, original str remains unchanged
System.out.println(str); // Output: Hello
str = str.concat(" World"); // Assigns the new String object to str
System.out.println(str); // Output: Hello World
Internal Implementation (Java 11+):
Internally, a String is represented as a byte[] array (since Java 9, to optimize memory usage for
non-Latin characters) instead of the earlier char[] array.
The String class uses a coder field to indicate the character encoding (LATIN1 or UTF16), enabling
compact storage of strings.
2. What is the String pool, and how does it work? Explain the difference between creating a String
using literals vs. the new keyword.
Answer:
The String pool (also known as the String intern pool) is a special area in the Java heap memory
(specifically, the PermGen space in Java 6 and earlier, or the Metaspace in Java 8+) where String
literals are stored and reused to optimize memory usage.
How the String Pool Works:
When a String literal (e.g., "Hello") is created, the JVM checks if an identical String already exists in
the String pool.
If it exists, the reference to the existing String is returned.
If it does not exist, a new String object is created in the pool, and its reference is returned.
The intern() method can be used to explicitly add a String to the pool or retrieve an existing one.
String Creation: Literals vs. new Keyword:
Using String Literals ("Hello"):
- The String is created in the String pool.
- If an identical literal already exists in the pool, the existing object is reused.
- Memory-efficient due to reuse.
Using the new Keyword (new String("Hello")):
- A new String object is created in the heap memory, even if an identical String exists in the pool.
- The String pool is not involved unless intern() is explicitly called.
- Less memory-efficient, as it creates a new object every time.
Example:
String s1 = "Hello"; // Stored in the String pool
String s2 = "Hello"; // Reuses the same object from the pool
String s3 = new String("Hello"); // Creates a new object in the heap
System.out.println(s1 == s2); // true (same object in the pool)
System.out.println(s1 == s3); // false (different objects)
System.out.println(s1 == s3.intern()); // true (s3.intern() refers to the pooled object)