Java String Interview Questions and Answers
π± 1. What is the difference between String
, StringBuilder
, and StringBuffer
? [Beginner β Intermediate]
String
is immutable, meaning once created, it cannot be changed. Any modification creates a new object.StringBuilder
is mutable and not thread-safe. It's faster for single-threaded scenarios where frequent modifications are needed.StringBuffer
is also mutable but thread-safe due to synchronized methods, so it's safer in multithreaded code but slower.
π Use String
for constant text, StringBuilder
for performance in single threads, and StringBuffer
for thread safety.
πΏ 2. Why is String
immutable in Java?
In Java, the String
class is immutable, meaning once a String
object is created, its value cannot be changed. Instead, any operation that appears to modify a string actually creates a new object.
π Why was String
made immutable?
π 1. Security
-
Strings are widely used in sensitive areas like:
- Network connections (
URL
,IP
) - File paths
- Class loading
- Database credentials
- Network connections (
-
If
String
were mutable, malicious code could change the contents (e.g., change a file path after permission is granted), leading to security risks.
π§΅ 2. Thread Safety
- Since strings are immutable, multiple threads can safely share the same
String
without synchronization. - This makes programming in multi-threaded environments easier and less error-prone.
β»οΈ 3. String Pool Efficiency
-
Java maintains a String pool (also called the intern pool) to avoid creating duplicate strings.
-
When strings are immutable:
- Reusing objects becomes safe and efficient.
String s1 = "hello"; String s2 = "hello";
β both point to the same object.
-
If strings were mutable, changing one would affect all references, breaking the pool's purpose.
πΊοΈ 4. Hash Code Caching (used in HashMap)
- Strings are often used as keys in HashMaps.
- Java caches the
hashCode()
value of a string after itβs calculated once. - If strings were mutable, modifying their content would make them useless as map keys because their hash would change.
πΏ 3. How does String pooling work in Java?
Java maintains a String Pool in the heap. When a string literal is created, the JVM checks the pool first:
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true
Here, both s1
and s2
point to the same object in the pool. No new object is created if it already exists.
However, using new String("hello")
creates a new object in the heap, not the pool.
π± 4. What is the difference between ==
and .equals()
when comparing Strings?
==
compares reference (memory address)..equals()
compares actual content (characters).
String a = "java";
String b = new String("java");
System.out.println(a == b); // false
System.out.println(a.equals(b)); // true
So always use .equals()
to compare string values.
π± 5. What does the intern()
method do?
The intern()
method ensures that a string is added to the String pool. If it already exists, it returns the pooled version. This helps reduce memory footprint.
String s1 = new String("apple");
String s2 = s1.intern();
String s3 = "apple";
System.out.println(s2 == s3); // true
πΏ 6. Why should you avoid using +
operator in loops for String concatenation?
The +
operator creates new String objects every time, which is inefficient in loops.
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // creates new object each time!
}
Instead, use StringBuilder
:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
This improves performance by avoiding object creation in every iteration.
πΏ 7. Is String
thread-safe?
Yes, because String
is immutable, it is inherently thread-safe. Multiple threads can access the same String
object without issues, as its value never changes.
π± 8. What are some commonly used methods in the String
class?
length()
: returns string lengthcharAt(int index)
: gets character at indexsubstring(start, end)
: extracts substringindexOf(String)
: finds position of substringsplit(regex)
: splits string into arrayreplace()
: replaces characterstoLowerCase()
,toUpperCase()
: case conversiontrim()
: removes whitespace
These methods make String
powerful for text manipulation.
π³ 9. What is the time complexity of the String.concat()
method?
The time complexity of concat()
is O(n), where n
is the length of the resulting string.
Since String
is immutable, a new character array is created and the contents of both strings are copied.
πΏ 10. How are strings stored in memory in Java?
String literals are stored in the String pool (part of heap memory). Other string objects (like created using new
) are stored in the regular heap.
References to strings can be on the stack, but the string data itself always resides on the heap.
πΏ 11. What happens when you use the +
operator with Strings in Java?
When you use the +
operator with Strings, Java internally uses a StringBuilder
(or StringBuffer
in older versions) to perform the concatenation. For example:
String result = "Hello" + " " + "World";
The compiler translates this to something like:
String result = new StringBuilder().append("Hello").append(" ").append("World").toString();
However, in loops, this optimization is not as effective because a new StringBuilder
is created in each iteration.
πΏ 12. What is the difference between substring()
in Java 6 and Java 7+?
In Java 6 and earlier, substring()
would share the same character array as the original string but with different offset and count values. This saved memory but could lead to memory leaks if you kept a small substring of a very large string.
In Java 7+, substring()
creates a completely new character array, copying only the required characters. This prevents memory leaks but uses more memory for the duplicate data.
πΏ 13. How does Java handle String encoding?
Internally, Java stores strings as UTF-16 encoded characters. Each character in a Java String is 16 bits (2 bytes). For characters outside the Basic Multilingual Plane (BMP), Java uses surrogate pairs (two char values).
When reading or writing strings to external sources, Java provides methods to convert between different encodings:
byte[] bytes = string.getBytes("UTF-8"); // Convert to UTF-8 bytes
String newString = new String(bytes, "UTF-8"); // Convert back to String
The default encoding depends on the platform's locale settings if not specified.
π± 14. What is the String.format()
method and how is it used?
The String.format()
method creates formatted strings using format specifiers, similar to C's printf()
. It's useful for creating complex strings with variables.
String formatted = String.format("Hello, %s! You have %d new messages.", username, messageCount);
Common format specifiers:
%s
- String%d
- Integer%f
- Float/Double%b
- Boolean%tc
- Date/Time
You can also specify precision, width, and alignment using modifiers like %.2f
for 2 decimal places.
π³ 15. How would you efficiently check if a String is empty in Java?
There are several ways to check if a String is empty:
// Check for null and empty string (Java 6+)
if (str == null || str.isEmpty()) {
// String is null or empty
}
// Check for null, empty, or whitespace (Java 11+)
if (str == null || str.isBlank()) {
// String is null, empty, or only whitespace
}
Avoid using str.length() == 0
as it doesn't handle null strings and will throw a NullPointerException.
π³ 16. What is the difference between String.matches()
and using Pattern
and Matcher
classes?
String.matches()
is convenient for one-time pattern matching, but it's inefficient for repeated use because it compiles the regex pattern each time:
boolean isEmail = email.matches("^[\\w.-]+@([\\w-]+\\.)+[\\w-]{2,4}$");
For better performance with repeated matching, use Pattern
and Matcher
:
Pattern pattern = Pattern.compile("^[\\w.-]+@([\\w-]+\\.)+[\\w-]{2,4}$");
Matcher matcher = pattern.matcher(email);
boolean isEmail = matcher.matches();
This approach compiles the pattern only once, making it much more efficient for multiple checks.
π³ 17. How can you compare strings ignoring case in Java?
To compare strings ignoring case, use the equalsIgnoreCase()
method:
String str1 = "Hello";
String str2 = "hello";
boolean areEqual = str1.equalsIgnoreCase(str2); // true
For sorting strings case-insensitively, use:
String[] names = {"Alice", "bob", "Charlie", "david"};
Arrays.sort(names, String.CASE_INSENSITIVE_ORDER);
π³ 18. What is a StringJoiner
and when would you use it?
StringJoiner
(introduced in Java 8) is a class that constructs a sequence of characters separated by a delimiter with optional prefix and suffix:
StringJoiner joiner = new StringJoiner(", ", "[", "]");
joiner.add("Apple").add("Banana").add("Cherry");
String result = joiner.toString(); // [Apple, Banana, Cherry]
It's particularly useful when you need to join elements with consistent formatting. The String.join()
method uses StringJoiner
internally:
String result = String.join(", ", "Apple", "Banana", "Cherry"); // Apple, Banana, Cherry
π³ 19. How does Java implement the hashCode()
method for String?
The String
class implements hashCode()
using a specific algorithm that iterates through each character:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
The hash is cached after first calculation for performance. This is why strings are immutable - changing a string after using it as a HashMap key would break the hash-based data structures.
π³ 20. What are some best practices for String handling in Java?
- Use
StringBuilder
for concatenation in loops - Prefer
equals()
over==
for comparison - Use
String.intern()
when working with many duplicate strings - Consider using
char[]
for sensitive data (passwords) as they can be explicitly cleared - Use
String.format()
for complex string formatting - Prefer
StringJoiner
orString.join()
for joining collections - Use
Pattern
andMatcher
for repeated regex operations - Be aware of encoding issues when converting between String and byte arrays
- Use
isBlank()
(Java 11+) instead ofisEmpty()
when whitespace should be considered empty - Consider memory usage with very large strings