String in Java - Top 25 Interview questions and answers with deep understanding of concepts



Q 1: What is String in Java?
Answer:  In Java, a String is represented internally by an array of byte values OR char values before JDK 9. In versions up to and including Java 8, a String was composed of an immutable array of Unicode characters. However, most characters require only 8 bits (1 byte) to represent them instead of 16 bits (char size).

To improve memory consumption and performance, Java 9 introduced compact Strings. This means that if a String contains only 1-byte characters, it will be represented using Latin-1 encoding. If a String contains at least 1 multi-byte character, it will be represented as 2 bytes per character using UTF-16 encoding.

Q2 : What is Compact String in Java 9?
Answer: Each String in Java is internally represented by two objects. First object is the String object itself and the second one is the char array that handles the data contained by the String. The char type occupies 16 bits or two bytes. If the data is a String in the English language for instance, often the leading 8 bits will be all zeroes as the character can be represented only by using one byte.

Strings occupy a major portion of heap space of JVM in any application. Since strings are immutable and reside in the string literal pool, developers can imagine how much memory could be used up by them till the garbage collection occurs. It thus makes sense to make the strings shorter or compact by discarding some data that do not have the added value.
A study on thread dumps of various Java applications revealed that most of the Strings in the applications were LATIN-1 characters, that can be represented by just using 8 bits. There were other special characters that needed all 16 bits but their frequency of occurrence was far less compared to LATIN-1 characters.
Lets take an example:
Diagram 1:

Under each byte, according to UTF-16 we have written the hexadecimal representation. This is how a String object is internally represented using char array till Java 8. Note that the bytes in light gray are not really needed to represent the characters. The actual data that matters in each 16 bits representing the English alphabets are the trailing 8 bits. Thus, by omitting these bytes, it is possible to save extra space.

Q3: How Is a String Stored in Memory?
Answer: According to the JVM Specification, String literals are stored in a runtime constant pool or String pool or String intern pool, which is allocated from the JVM's method area.
Although the method area is logically part of the heap memory, the specification does not dictate the location, memory size, or garbage collection policies. It can be implementation-specific.
This runtime constant pool for a class or interface is constructed when the class or interface is created by the JVM.

Q 4: Is String a Primitive or a Derived Type?
Answer:A String is a derived type since it has state and behavior. For example, it has methods like substring(), indexOf(), and equals(), which primitives cannot have. But, because of its some special characteristics that make it feel like a primitive:
  1. While strings are not stored on the call stack like primitives are, they are stored in a special memory region called the string pool
  2. Like primitives, we can use the + operator on strings
  3. And again, like primitives, we can create an instance of a String without the new keyword

Q 5: What are different ways to create String Object?
Answer: There are 13 different ways of creating string object, which is defined in java.lang.String. Still, in real life generally below two ways mostly used to create string object:
 a. Through a String literal:
              String s = "abc";
b. Through the new keyword:
              String s = new String("abc");
All String literals in Java are instances of the String class.

Q 6: What is String Pool?
Answer: The String constant pool also known as the the String intern pool or String pool, is a special memory region where the JVM stores String instances.
It optimizes application performance by reducing how often and how many strings are allocated:
  • The JVM stores only one copy of a particular String in the pool
  • When creating a new String, the JVM searches in the pool for a String having the same value
  • If found, the JVM returns the reference to that String without allocating any additional memory
  • If not found, then the JVM adds it to the pool (interns it) and returns its reference

Q 7: What is the difference in String pool between Java 6 and 7?
Answer: Below are  the important difference in String pool in Java 6 and 7:
  1. String pool is relocated to Java heap space from PermGen space.
  2. The default size of String pool is increased to 600013 entries from 1009 in Java 6.
  3. The -XX:StringTableSize JVM option is provided to specify the size of String pool.
Q 8: What is String intern?
Answer: String object in the string constant pool is called as String Intern. You can create an exact copy of heap memory string object in string constant pool. This process of creating an exact copy of heap memory string object in the string constant pool is called interning. intern() method is used for interning.
Example:

In the above example:
  • When we are calling s3.intern(), JVM checks if there is any string in the pool with value “Tanuja” is present? Since there is a string object in the pool with value “Tanuja”, its reference is returned.
  • Notice that we are calling s4 = s3.intern(), so the s4 is now referring to the string pool object having value “Tanuja”. That's why  s1==s4 returns true.
Q 9: When to use intern() method?
Answer: The String.intern() method can be used to deal with the String duplication problem in Java. By carefully using the intern() means you can save a lot of heap memory consumed by duplicate String objects. A String object is said to be duplicate if it contains the same content as another string but occupied different memory location e.g. str1 != str2 but str1.equals(str2) is true. Since String object consumes a large amount of heap memory in average Java application, it makes sense to use the intern() method to reduce duplication and take advantage of String pool feature provided by Java.

Q 10: Does String is thread-safe in Java?
Answer:Strings are indeed completely thread-safe because they are immutable. Any class which is immutable automatically qualifies for thread-safety because its immutability guarantees that its instances won't be changed across multiple threads.

Q 11: Why String is popular HashMap key in Java?
Answer: When you create a HashMap object and try to store a key-value pair in it, while storing, a hash code of the given key is calculated and its value is placed at the position represented by the resultant hash code of the key. When you pass the key to retrieve its value, the hash code is calculated again, and the value in the position represented by the hash code is fetched (if both hash codes are equal).

Suppose we used a certain variable as key to store data and later we modified the value of this variable. At the time of retrieval, since we changed the key, the hash code of the current key will not match with the hashCode at which its value has been stored making the retrieval impossible.

Since the String class is immutable, you cannot modify the value of a String once it is created. Therefore, it is recommended to use a String variable to hold keys in hash a map.

Q 12: Why is String final in Java?
Answer: I can think of below five options while thinking about immutability or final of string:

1.String Pool:  
This is the special memory region where Strings are stored by the JVM. Since Strings are immutable in Java, the JVM optimizes the amount of memory allocated for them by storing only one copy of each literal String in the pool.

2.Security:
The String is widely used in Java applications to store sensitive pieces of information like usernames, passwords, connection URLs, network connections, etc. It's also used extensively by JVM class loaders while loading classes.
Hence securing String class is crucial regarding the security of the whole application in general.

3.Synchronization:
Being immutable automatically makes the String thread safe since they won't be changed when accessed from multiple threads.
Hence immutable objects, in general, can be shared across multiple threads running simultaneously. They're also thread-safe because if a thread changes the value, then instead of modifying the same, a new String would be created in the String pool. Hence, Strings are safe for multi-threading.

4.Hashcode Caching:
Since String objects are abundantly used as a data structure, they are also widely used in hash implementations like HashMap, HashTable, HashSet, etc. When operating upon these hash implementations, hashCode() method is called quite frequently for bucketing.
The immutability guarantees Strings that their value won’t change. So the hashCode() method is overridden in String class to facilitate caching, such that the hash is calculated and cached during the first hashCode() call and the same value is returned ever since.

5.Performance:
As we saw previously, String pool exists because Strings are immutable. In turn, it enhances the performance by saving heap memory and faster access of hash implementations when operated with Strings.
Since String is the most widely used data structure, improving the performance of String have a considerable effect on improving the performance of the whole application in general.

Q 13: How will you create an immutable class in java?
Answer: You can create immutable class in java by implementing below points:

1. Make the class final so it can not be extended(inherited)
2. Make all fields private so one can not access them from outside the class.
3. Do not provide setter methods for the variables.
4. Declare all mutable fields as final so that it's value can be assigned only once.

Q 14: Is string thread-safe in Java?
Answer:  Yes, string is thread-safe as Strings are immutable, so we can’t change it’s value in program. And its safely used in multi-threaded environment.

Q 15: Is it possible to call String class methods using String literals?
Answer: Yes, It is possible to call String class methods using String literals. For example
"coreJava".indexOf(r);
"coreJava".charAt(0);
"coreJava".compareTo("coreJava");

Q 16: How substring method of String works internally in java? How they create memory leaks? How to resolve memory leak issue?
Answer: substring() method has two different implementation in 6 and Java 7 release. 
In Java 6, substring() method creates memory leak issue. Lets see how substring works internally in java 6 or prior to java versions:
In Java 6:
Every time you call substring() method in Java, it will return a new String because String is immutable in Java. A String is basically a char[] that contains the characters of the string with an offset and a count (i.e. the string is composed of count characters starting from the offset position in the char[]).
When calling substring, a new string is created with the same char[] but a different offset / count, to effectively create a view on the original string, Except when count = length and offset = 0 as it will return same string array as mentioned in below code snippet of String Class in Java 6.

//String Class code in Java 6.
String(int offset, int count, char value[]) {
	this.value = value;
this.offset = offset;
this.count = count;
}
public String substring(int beginIndex, int endIndex) {
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
Consider a scenario where original string is very long, and has array of size 1GB, no matter how small a substring is, it will hold 1GB array. This will also stop original string to be garbage collected, in case if doesn’t have any live reference. This is clear case of memory leak in Java, where memory is retained even if it’s not required. That’s how substring method creates memory leak.
In Java 7:
To resolve memory leak issue in older Java versions, Instead of sharing original character array, substring method creates a copy of it.
New char[] is created every time, because there is no more offset or count field in the string class.
As mentioned in below code snippet, Arrays.copyOfRange is used to create whole new copy of substring.

// String.java Java 7
public String substring(int beginIndex, int endIndex) {
int subLen = endIndex - beginIndex;
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
public String(char value[], int offset, int count) {
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
Solution for memory leak in Older versions of Java:
1. If you want to use an old JDK (that is older than OpenJDK 7) and you want to have minimal strings 
after substring, use the constructor taking another string :
String s2 = new String(s1.substring(0,1));
2. Another way to to solve this problem is to call intern() method on substring, which will than fetch an existing String from pool or add it if necessary. 
Since the String in the pool is a real string it only take space as much it requires. It’s also worth noting that sub-strings are not internalized, when you call intern() method on original String.
Q 17: Are Interned Strings Eligible for Garbage Collection in Java?
Answer: Yes, all Strings in the string pool are eligible for garbage collection if there are no references from the program.
Q 18: How will you create an immutable class in java?
Answer: You can create immutable class in java by implementing below points:

1. Make the class final so it can not be extended(inherited)
2. Make all fields private so one can not access them from outside the class.
3. Do not provide setter methods for the variables.
4. Declare all mutable fields as final so that it's value can be assigned only once.
Q 19: Explain the difference between str.equals("xyz") and "xyz".equals(str), where str is any String object? 
Answer: If str value is "xyz" then both statements will give the result true. Main difference between the two statement arises when we pass str value as NULL.
If the str is null then first statement will throw null pointer exception while second statement will return false.


Q 20: Can we use string for switch statement?
Answer: Yes to version 7. From JDK 7, we can use string as switch condition. Before version 6, we can not use string as switch condition.

// java 7 onwards
switch (str.toLowerCase()) {
      case "a":
           value = 10;
           break;
      case "b":
           value = 20;
           break;
}
Q 21: What is the difference between the String and StringBuffer? 
Answer: The String is a final class in Java. The String is immutable. That means we can not change the value of the String object afterword. 
Since the string is widely used in applications, we have to perform several operations on the String object. Which generates a new String object each time, and all previous objects will be garbage object putting the pressure on the Garbage collector. 
Hence, the Java team introduced the StringBuffer class. It is a mutable String object, which means you can change its value. The string is immutable, but the StringBuffer is mutable.

Q 22: What is the difference between the StringBuffer and StringBuilder? 
Answer: We know String is immutable in Java. But using StringBuffer and StringBuilder, you can create mutable or editable string objects. 
When Java Team realizes the need for the editable string object, they have introduced the StringBuffer class. But all the methods of the StringBuffer class are synchronized. 
That means at a time, only one thread can access a method of the StringBuffer. As a result, it was taking more time. 
Latter, Java Team realizes that making all methods of the StringBuffer class synchronized was not a good idea, and they introduced a StringBuilder class. None of the methods of the StringBuilder class are synchronized. Since all the methods of the StringBuffer class are synchronized, StringBuffer is thread-safe, slower, and less efficient as compared to StringBuilder. 
Since none of the methods of the StringBuilder class is synchronized, StringBuilder is not thread-safe, faster, and efficient as compared to StringBuffer.

Q 23: How do you compare two String in Java? What’s the Difference Between str1 == str2 and str1.Equals(str2)?
Answer: We can compare strings in two different ways: by using equal to operator ( == ) and by using the equals() method.
Both are quite different from each other:
  • The operator (str1 == str2) checks for referential equality
  • The method (str1.equals(str2)) checks for lexical equality
Though, it's true that if two strings are lexically equal, then str1.intern() == str2.intern() is also true. Typically, for comparing two Strings for their content, we should always use String.equals.

Q 24:Why char[] array is better than String for storing password?
Answer: Since strings are immutable, they don't allow modification. This behavior keeps us from overwriting, modifying, or zeroing out its contents, making Strings unsuitable for storing sensitive information.
We have to rely on the garbage collector to remove a string's contents. Moreover, in Java versions 6 and below, strings were stored in PermGen, meaning that once a String was created, it was never garbage collected.
By using a char[] array, we have complete control over that information. We can modify it or wipe it completely without even relying on the garbage collector.
Using char[] over String doesn't completely secure the information; it's just an extra measure that reduces an opportunity for the malicious user to gain access to sensitive information.

Q 25. Are Interned Strings Eligible for Garbage Collection in Java?
Answer: Yes, all Strings in the string pool are eligible for garbage collection if there are no references from the program.

Comments