Why String is final or immutable in Java with Example

Before going  into details as why String is final or immutable in java , first let us understand the meaning of the term "immutable".


What does immutable means?

According to our good buddy, “thefreedictionary”, immutable means “not capable or susceptible to change”.


Note : In java , if an object is immutable then it can not be changed after creation.




How Strings are immutable ?

The String Class

The String class represents a set of characters enclosed in a pair of double quotes (“”). All String literals in Java, such as "hello", are implemented as instances of the String class. 

Strings are immutable; their values cannot be changed after they have been created, while StringBuffers and StringBuilders supports mutable versions of the String object.

For example: 
     String str = "hello";  

is equivalent to:       
char ch[] = {'h', 'e', 'l', ‘l’, ‘o’};      
String str = new String(ch); 

There are several ways on how to create a String object, by checking the Java API documentation; you’ll see that the String class has about 15 constructors including the 2 deprecated ones. Deprecated constructors and methods are encouraged not to be used in the current Java version.

Here are the two common ways on how to create a String object.

String str1 = new String(“hello”);
String str2 = “java”;

The first one uses the keyword new followed by the String constructor; while the second one uses a direct assignment.

  • Is there a difference between the two? Let’s take a look at the two code snippets; this will also explain why String objects are immutable.




Sample Code Snippet #1:
String str1 = new String("java");
String str2 = new String("java");
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));


why string is immutable or final in java -1


Snippet Output #1:
false
true


That’s why when str1 and str2 was compared using the double equals operator (==), the output was false because they were comparing the addresses of both variables. The .equals method on the other hand compares if both str1 and str2 have identical String objects that they are referring to.

Sample Code Snippet #2:
String str1 = “java”;
String str2 = “java;
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
same memory address string


Snippet Output #2:
true
true




Snippet #2 created only 1 object but had two variables holding them. That is why str1 and str2 has the same address. Therefore when they are compared using the double equals operator (==) they returned true. A second String object was not forcibly created because the constructor was not explicitly called. The statement str2 = “java” only assigns the already existing String object in the memory to the String variable str2.

During concatenation, we can also see that the String object also shows their immutability by creating a new object after concatenation. Concatenation can be done by calling the concat method or by using the concatenation symbol (+).

Sample Code Snippet #3:

String str = “hello ”;
string having memory address






str = str + “world”;
System.out.println(str);

is the same as:

String str = “hello ”;
str.concat(“world”);
System.out.println(str);

String is pointing to new memory address


Both sample codes will printout hello world as the output.

Here’s the explanation:

String str = “hello ”; 

str.concat(“world”);


After concatenating the Strings “hello ” and “world”, it will produce a new object “hello world” which is a new object that has a new address.


3. Why Strings are immutable.

Security is one of the reasons that I can think of why String objects are immutable. Strings are usually used as parameters in several Java methods that can be used to access data sources like databases, files or even objects that can be found across the network. Once you call a method that takes  an immutable object like Strings, you can be sure that the data that is passed won’t change. It simply cannot change.

Imagine the threat and security problems that you may have if you are accessing a method via RMI (Remote Method Invocation) and the method that you are calling requires you to pass a String object. Before reaching the requested method, there is no assurance that the String objects that you sent is the same String object that is received on the other VM (Virtual Machine). This can result to a serious security problem.


4. What do I use if I need a mutable version of a String object? 

Incase you are in need of mutable String objects, you may use StringBuffer or StringBuilder. Both are found inside the java.lang package and both classes contains the same set of methods that can change the object like append, insert, reverse and a lot more. Both of these classes can also take in a String object as a parameter on their respective constructors.

Here’s how to create StringBuffer and StringBuilder objects that accepts a String parameter.

StringBuffer sBuffer = new StringBuffer(“this is a string”);
StringBuilder sBuilder = new StringBuilder(“this is another string”);



The difference between StringBuffer and a StringBuilder object is the thread safety capability.

StringBuffer can not be used by multiple concurrent users because it is thread-safe. But StringBuilder is not thread-safe; therefore it can only be used by multiple threads.

Thread-safety also has its minor trade off. Thread-safe objects like StringBuffer objects may require a slightly larger memory space during runtime compared with StringBuilder  objects. This is because during runtime, the thread activation and passivation process can happen at runtime if the thread-pool ran out of threads. This is the reason why most of the mobile devices like PDA’s, mobile phones and terminal card readers only uses StringBuilder and not StringBuffer. Aside from having a smaller memory requirement, StringBuilder are also used by a single process only. 




5. The String class is a final class.

According to the Java API Documentation the String class declaration is:

public final class String extends Object
implements Serializable, Comparable<String>, CharSequence

Declaring a class as final means that the class cannot be extended by another class. You cannot create a subclass from a final class.

Here’s a non-working Code Snippet:

public class MyStringVersion extends String
{}

This snippet won’t compile because the class MyStringVersion  is extending the class String.

This simply shows that the String class cannot be extended or inherited. This is good.


Imagine, if Strings are not final, you can create a subclass and instantiate two objects from different classes that can look alike and be seen as Strings but are actually different. This can cause several problems in so many levels. Thats it for now just mention in comments if you have any other questions related to why string is immutable or final in java. 

About The Author

Subham Mittal has worked in Oracle for 3 years.
Enjoyed this post? Never miss out on future posts by subscribing JavaHungry