Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
Java is an object-oriented programming language that has many predefined data structures. Different data structures store different types of data like arrays are used to store homogenous elements at contiguous memory locations. One such data type in Java is String. Strings are used to store a sequence of char values. An array of characters works the same as a string. Arrays are of a fixed size that is, they are immutable therefore, strings are immutable as well. In this blog, we will discuss why strings in Java are immutable?
An immutable object is an object whose value cannot be changed after it is created. If you want to modify it, a new object is created instead of changing the existing one.
Example in Java:
String str = "Hello";
str = str + " World"; // A new String object is created, old one remains unchanged
What is an Immutable String in Java?
In Java, a String object is immutable, meaning its content (sequence of characters) cannot be changed after it is instantiated. Any operation that appears to modify a String actually creates a new String object. This immutability is enforced by making the String class final and ensuring that its methods do not modify the internal character array directly. This property of String objects in Java makes them inherently thread-safe and simplifies memory management.
The above example creates a string containing “Hello” and assigns it to reference string1.
The string class provides a large number of predefined functions that allow the programmer to manipulate strings. Some of the predefined functions are equals(), concat(), etc.
The above statement creates a new string: string2, and appends a string “World” to it.
When the Java Virtual Machine executes the above statement, it takes the value of String string1, i.e., “Hello” and appends “World”, giving us the value “Hello World”. As Strings are immutable, the Java Virtual Machine can’t assign this value to string2, so it creates a new String object, assigns it the value “Hello World” and gives its reference to string2.
String Objects are immutable, but their reference variables are not. In the example above, we have three String objects: the first one being “Hello” which is pointed by string1, the second one being “Hello World” pointed by string2, and the third one being the literal “World” in the concat statement.
Some of the reasons why Strings are immutable in Java are :
Heap Space
If Strings are not immutable, then the String pool and String interning won't be possible. Java Runtime Environment saves a large amount of heap space. The same string variable can be referred to by more than one string variable in the pool.
Security
If strings are not made immutable, then there will be a serious security threat to the application. For example, usernames and passwords are stored in Strings. Even the socket programming host and port description are passed as strings. Just because strings are immutable, their value cannot be changed. But if strings don't remain immutable, any hacker can cause a security issue in the application by changing the reference value.
Thread Safe
Multithreading is possible with strings because of their immutableness. Different threads can access a single “String Instance”.
ClassLoader
Classloader uses string objects as an argument in Java. If the string object can be modified, its value can be changed, and because of this, the class that will be loaded will be different. To avoid such misinterpretation, strings are immutable.
Facts regarding strings and memory usage
Java
Java
import java.io.*;
class Example { public static void main(String[] args) { String string1 = "Hello"; string1.concat("World");
// Yes, string1 still refers to "Hello" System.out.println("string1 refers to " + string1); } }
You can also try this code with Online Java Compiler
We initially created a new String in the above code, “Hello” and string1 refers to it. Then the VM creates another new String, “Hello World”, but nothing refers to it. Because of this, the second String is lost and cannot be reached. The reference variable string1 still refers to the original string “Hello”. Every method except a few, which, when applied to a String object, creates a new String object. If no variable refers to it, then where do these String objects go? Such Strings exist in memory, and one of the key goals of any programming language is to make efficient use of memory. As the application grows in size, the string literals start occupying a large area of memory, which causes redundancy. Java Virtual Machine sets aside a special area of memory which is known as String Constant pool.
Whenever the compiler sees a String literal, it searches for that String in the pool. If a match is found, then the reference to that new literal is directed to the existing String. No new String object is created in such cases, and the existing String has one more reference.
In the String constant pool, a String object is likely to have more than one reference. If several references point to the same String without even knowing it, then it would be dangerous if any of the references modified that String value. This is why String objects are immutable.
When JVM executes the statement String string1=”Hello”, it will create a String object in the string constant pool and store “Hello” in it.
When the statement string2.concat(“World”) will be executed then, the JVM will create two new objects because we are trying to modify the original content.
Initially, for every String literal “World”, the JVM will create a copy of the string object in the string constant pool.
Then the second object will be created in the heap with the modified content “Hello World”. The string concatenation statement is executed at the runtime. Therefore if a new object is to be created, the object will always be created in the heap area and not in the string constant pool.
As this new object is not assigned to any reference variable, therefore it is known as an unreferenced object. The garbage collector will automatically remove this from memory.
The immutability of String objects in Java provides several advantages:
Thread Safety: Since String objects are immutable, they can be shared between multiple threads without the risk of one thread modifying the string while another thread is using it. This simplifies concurrent programming and eliminates the need for synchronization in most cases.
Security: Immutable strings are inherently secure because their values cannot be changed once they are created. This property is particularly useful in scenarios where sensitive information, such as passwords or cryptographic keys, is stored as strings.
Caching: Due to immutability, Java runtime can optimize string usage by storing commonly used strings in a string pool. This allows multiple references to the same string literal to point to the same object, reducing memory footprint and improving performance.
Hashcode Stability: The immutability of String objects ensures that their hashcode (used in hash-based collections like HashMap and HashSet) remains constant throughout their lifetime. This makes String objects suitable as keys in hash-based data structures.
Easy Concatenation and Composition: Since modifying strings in Java involves creating new strings, operations like concatenation (+ operator or concat() method) or substring creation return new String objects without altering the original ones. This functional approach simplifies string manipulation and enhances code clarity.
Performance: Immutable objects, including strings, can be optimized by the compiler and runtime environment. String interning (storing only one copy of each distinct string value) and constant folding (evaluating constant expressions at compile-time) are possible due to immutability, leading to better performance in Java applications.
Demerits of Using String
Since String is immutable in Java, it has some drawbacks:
1. Memory Consumption
Every time you modify a string (e.g., concatenation), a new object is created, and the old one remains in memory until garbage collection.
This leads to higher memory usage, especially in large applications with frequent string operations.
Example:
String s = "Hello";
s = s + " World"; // A new object is created, increasing memory usage
2. Performance Overhead
Since modifying a String creates new objects, it slows down performance in scenarios with frequent string modifications.
Operations like concatenation in loops can be inefficient.
Solution: Use StringBuilder or StringBuffer instead of String for better performance.
Example:
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // Modifies the existing object, no new object creation
3. Increased Garbage Collection
Due to frequent creation of new String objects, garbage collection load increases, affecting overall application performance.
Unused string objects pile up in the heap memory, requiring frequent cleanup.
4. Not Suitable for Large Data Processing
If you’re handling large text data, using String can be inefficient due to immutability.
For tasks like file parsing, logging, or XML/JSON processing, StringBuilder is a better choice
Frequently Asked Questions
Which are immutable in Java?
Immutable classes in Java include String, Integer, Double, Long, Boolean, Byte, Short, Float, Character, and LocalDate. Their values cannot be changed after creation.
What is StringBuffer in Java?
StringBuffer is a mutable class used for string manipulation. It is more efficient than String for modifications and is thread-safe due to synchronized methods.
Is String thread-safe in Java?
Yes, String is thread-safe because it is immutable. Multiple threads can access the same string without risk of modification or data inconsistency.
Conclusion
In this article, we have extensively discussed why strings are immutable in the Java programming language.
After reading about the immutability of strings in Java, are you not feeling excited to read/explore more articles on Strings? Don't worry; Coding Ninjas has you covered. To learn about special string functions in Java, strings in Java, and how to print all the permutations of a string.