Hello guys, after looking into some intense topics, it is time to pick some simple ones. So, in this blog, we are going to talk about String class and String Pool. Let us begin…
String class is one of the widely used classes all around the globe. It is used right from storing a simple string such as name to the encrypted passwords.
If you see the String class definition, it has been declared as final. So once the String object is created, it cannot be modified. Have you ever thought about why it is immutable?. Let us find the answers…
Let us take any login system where you enter your username and password. If String had been mutable, then anyone would have changed the content of the String object and your account would have been compromised.
The String object is one of the widely used candidates for HashMap keys. Since String is immutable, its hashcode is cached at the time of creation and doesn’t need to be calculated again. This makes the String object a great candidate for the key in the Map.
String immutability also helps in saving a lot of heap space as String literals are cached in the String Pool. So, whenever JVM encounters a new string literal, it first checks whether it is present in the String Pool. If it is present, it returns that object reference otherwise it creates a new one in the String Pool, and then the reference of that object is returned.
Some of them might be having a doubt why the following statements are allowed if String is immutable.
In the above program, you might say that since String is immutable then why compiler allows you to change the value of str1. But if you see, you are not changing the value, you are just changing the reference. The JVM creates 2 different objects in String Pool. Don’t worry guys, we will look into another example where all your doubts will be cleared. But let us first understand String Pool.
A String Pool is a memory area where all string literals are cached by default. So whenever you create a new string literal, it first checks whether it is present in the String Pool. If yes, it returns the reference otherwise, it creates a new one in String Pool, and then the reference of that new one is returned.
Whenever you create a string using a new operator, the String object is created in the Heap Memory. But you can add that String object in the String Pool by using the intern method.
Prior to Java 7, the JVM placed the Java String Pool in the PermGen Space which has a fixed size — it can’t be expanded at runtime and it is not eligible for garbage collection. So, it can easily go out of memory if you create too many string literals or if you intern to many string objects. To avoid this, the String Pool was moved to the heap space from JDK 7 which is now eligible for garbage collection. The advantage here is that it reduces the chances of out of memory error as unreferenced strings are garbage collected. Don’t worry if you are not aware of PermGen. I will cover it in my upcoming blogs.
Let us understand Strings with the help of an example
The Byte Codes
Let us examine each statement
- The first statement, variable a holds a string literal “abc”. The compiler recognizes and marks it for the String pool. If you see the corresponding byte code, it has an instruction ldc, which means load string “abc” from the String Pool.
- The next statement is a concatenation of 2 string literals. Instead of storing 2 string literals in the String Pool, the compiler performs some optimization by combining both the strings and then storing it in the String Pool. See the corresponding byte code.
- The next statement is also a concatenation operation but this time we are using variable a and a string literal “123”. Since “123” is a string literal, it is marked for the String Pool. But in this case, the compiler cannot perform concatenation operation as it doesn't have string object “123”. The reason behind this is that all objects are created at runtime. The ldc command is used for the string literal “123” and for concatenation, the JVM uses StringBuilder and stores it in the heap memory. So always keep in mind, all string literals are stored in String Pool by default.
- The next statement is a string literal and it is stored in String Pool
- Now, let us jump to 1st print statement. What do you think the output of the first print statement? THINK!!!!
- The output is false (Equal to checks memory reference) because the string object (a + “123”) is constructed in the heap memory whereas the string object d = “abc123” is constructed in the String Pool.
- The next instruction is String e = new String(“xyz”). Here “xyz” is a string literal, so it is stored in the String Pool. But another string object with value as “xyz” is created in the heap memory as we are using new operator.
- Now, if you try to compare the memory reference of “xyz” and string object e created by new operator, the output will be false as “xyz” is stored in a string pool whereas string object e is stored in the heap memory.
- The String class provides an intern method that has dual functionality. It is used to create a copy of a string object present in the heap memory and then put that copy in the String Pool. In the statement, String f = e.intern(), a copy is created and it is stored in the String Pool. Now, if I try to compare “xyz” with the copy, the result will be always true.
I hope you guys understood the internals of the String class. That’s it from this blog. I hope you guys liked it and yes, do send me your feedback.