String in Java is immutable

Lakshini Kuganandamurthy
Nerd For Tech
Published in
7 min readApr 10, 2022
Java String

Ok, I know most of you all know this!!! I knew it too!!! But did we correctly understand the term “immutable” and do we know why Strings are immutable in Java???

Ok, let’s dig in!!!

What is immutability???

In simple terms, Once an object is created, it cannot be modified or changed. A value and an object are two different terms in Java. Value is what an instance variable or a reference variable holds. An instance variable holds the actual value (based on the type) that e.g. a programmer provides. For e.g.

int a = 123;
float s = 65.7;
String name = "Lakshi";

As you already know objects in Java are stored in the Heap area of the memory area in JVM. Refer to my article on JVM architecture, for a better understanding. Therefore, a reference variable holds the memory address of the object it is pointing to, as its value. The figure below illustrates a reference variable “s”.

Illustration of a reference variable

Whereas an object is an instance of a class with many instance variables generally referred to as “properties”.

String is a class in Java. Therefore, any variable declared with type “String” becomes a reference variable pointing to an instance of String class (i.e. String object). As shown below, a variable “name” is assigned the value “John”. Later we change the value of the variable to “Jane”. So here, only the values of the reference variable, “name” is changed. The String object which is given the value “John” is never changed, when the “name” variable got modified to “Jane”.

String name = "John";
name = "Jane";

Confusing right??? Let’s dig in to see what happens in the stack and heap areas of the memory, for the code above!!!

As we said earlier, any object created in Java is stored in the Heap. When the “name” variable is assigned “John”, JVM creates an object in the Heap and sets its value to “John”(because, a String value is assigned, String is a class in Java, therefore a String object gets created). The “name” variable points to this object. This is illustrated below.

Illustration of object reference

Later, when “name” is assigned “Jane”. This creates another String object and sets its value to “Jane”. Now, where does the “name” variable point to??? Yes, the “name” variable dereferences from “John” object and points to “Jane” object, as shown below.

Note that these are String objects which are given values “John” and “Jane”.

Referencing with Objects

So, did we change or modify the object??? No, but a new String object was created (Jane object) and the “name” variable starts pointing to the newly created object, i.e. the “name” variable now points to a different location in the heap (a different memory address). So, this implies that whenever you modify the value of the “name” variable, it creates a new Object with that value and “name” will point to that object thereafter!!! This is how String in Java is immutable!!!

Just a reminder, note that both objects have different memory addresses, in the heap.

Let’s see the reason why Java String was designed to be immutable!!!

Why Java String is immutable???

Observe the below code. These are three reference variables of type “String” having the same value “John”. We compare all three variables using the “==” and .equals() function.

This is represented in the Heap memory as follows.

Heap representation for he above code

The “==” compares the reference (memory address of the object pointing to) of the variables, since all the variables are pointing to the same object, the first 3 print statements will return “true”

The .equals() function compares the values of the objects, these variables point to, since all the variables point to the same object having the value “John”, the last 3 print statements too will return “true”.

Let’s say the String “John” occupies 4 bytes of heap memory. What if there were 1000 variables, assigned the value, “John”. There will be 1000 objects created in the heap with the value “John”. Therefore, it will occupy 4000 (4 x 1000) bytes of memory. Isn’t this a waste of heap memory, objects with the same value occupying this much space!!!

Yes, that is why Java uses a String pool to store String literals.

Java’s String pool

A String pool is a storage area in the heap. Whenever a variable is declared with the type String (reference variable to a String object), a String object (to which the variable points) is created occupying space in the heap. Creating the same objects many times, in the heap, will reduce memory space and performance.

The string pool is maintained by the String class in Java. Therefore, the String class creates a pool of String literals, to decrease the number of String objects created in the JVM heap. Now, when a String literal is created (a String value assigned to the reference variable), JVM first checks the String pool for that literal. If the literal is already present in the pool, it returns a reference to the pooled instance (i.e. it will return the value stored in the reference variable that is already pointing to that literal, this will make the new reference variable start pointing to the object in the pool, this way the same object can be referenced by 1000s of variables saving heap space). If that literal is not present in the pool, JVM creates a new String Object (the literal as the value) in the String pool. It is also good to note that only distinct String objects are stored in the String pool!!!

Also, note that there are 2 ways to create String Objects in the heap, in Java.

  1. Using String literal, e.g.
String str1 = "Python";
String str2 = "Data Science";

2. Using the “new” keyword

String str4 = new String("Java");
String str5 = new String("C++");

Let’s consider the below code.

The heap and stack representations are as follows.

Representation of heap and Stack when the “new” keyword is used

Here, whenever the “new” keyword is used to create String objects, we are asking JVM explicitly, to create a String object. Therefore JVM will create a String object with the value “John”, outside the String pool and “employee” will point to that object hereafter, as shown above.

So, when comparing “person” or “name” variables with “employee” using the “==”, will return false because the “employee” points to a different location (reference) in the heap now.

The .equals() function will anyway return true because all three variables point to objects with the same value, “John”.

Representation of Heap and Stack when the “new” keyword is used

Likewise when comparing “str1” and “str3” using “==”, will return true, because both refer to the same object. But “str1” or “str3” compared with “str5”, will return false, as “str5” points to the object explicitly created in the heap (using “new”).

Note that all the String objects created with the “new” keyword take place in the heap and not in the String pool.

Also as said earlier, when “str1” is assigned “Python”, JVM checks the String pool, since it is not present, it will create the respective String object in the String pool. The same applies to “str2” assigned with “Data Science”. Later when “str3” is assigned “Python” again, JVM checks for the “Python” object in the String pool, since it is already present, it returns the reference of the pooled instance, i.e. str1, without creating a new String object in the String pool.

The String class is able to maintain a String pool, basically because String in Java is immutable.

Emphasize again!!!

Immutability does not mean you cannot change the value of the reference variable but means you cannot change the object created!!!

Java String is Thread-safe

Because String is immutable, it is thread safe too. Let’s say there is a method that takes the “name” variable as a parameter as shown below. The “name” variable points to the “John” object in the heap.

public class Application {   public static void main(String args[]){
givePromotion("John");
}
public void givePromotion(String name){
//promotion code
}
}

A Java program can create many threads (non-daemon) when running. Assume that two threads are accessing the same method concurrently. If Java String was not immutable, when one thread is executing the givePromotion() method, another thread could modify the value of the String object from “John” to “Jane”. The executing thread takes the “name” (pointing to the same String Object but with a different value) as “Jane” and a different employee may get the promotion. This is illustrated below.

Illustration if String object is not immutable

Because String objects are immutable, one thread cannot modify the object created, when the other is executing the respective method. Therefore, same String object can be accessed by multiple threads concurrently.

Phew!!! A lot to understand right!!! Take it slow and you’ll grab it!!!

Happy Learning!!!

--

--

Lakshini Kuganandamurthy
Nerd For Tech

A passionate individual eager to learn and improve. Associate Software Engineer, Virtusa.