Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
In Java, objects are classified as mutable or immutable based on whether their state can be changed after creation. Mutable objects allow modifications, whereas immutable objects remain constant once assigned. Strings and wrapper classes are examples of immutable objects, while collections and custom classes with setter methods are mutable. Understanding mutability helps in writing efficient, thread-safe code.
In this article, you will learn the differences, benefits, and examples of mutable and immutable objects in Java.
Mutable Objects
A mutable object is an object whose state can be changed after it is created. In Java the StringBuilder and StringBuffer classes are used to create mutable strings. These classes allow modification of string content without creating new objects, making them memory efficient.
Example
public class MutableStringExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
System.out.println("Before modification: " + sb);
sb.append(" World");
System.out.println("After modification: " + sb);
}
}
You can also try this code with Online Java Compiler
Before modification: Hello
After modification: Hello World
Explanation:
StringBuilder allows us to modify the string without creating a new object.
The append() method modifies the existing string rather than creating a new one.
How to Create a Mutable Class
A mutable class in Java is one where the state (or data) of the object can be changed after it is created. This means you can modify the values of its fields without creating a new object. Mutable classes are useful when you need to update the object’s state frequently.
To create a mutable class, you need to follow these steps:
1. Define the class with private fields: These fields will store the data.
2. Provide public setter methods: These methods allow you to modify the values of the fields.
3. Provide public getter methods: These methods allow you to access the values of the fields.
Let’s create a simple mutable class called `MutableString`. This class will have a single field called `value` to store a string.
public class MutableString {
// Step 1: Define a private field
private String value;
// Step 2: Provide a constructor to initialize the field
public MutableString(String value) {
this.value = value;
}
// Step 3: Provide a getter method to access the field
public String getValue() {
return value;
}
// Step 4: Provide a setter method to modify the field
public void setValue(String value) {
this.value = value;
}
// Optional: Override toString() for better readability
@Override
public String toString() {
return "MutableString{" +
"value='" + value + '\'' +
'}';
}
}
You can also try this code with Online Java Compiler
1. Private Field: The `value` field is private, meaning it cannot be accessed directly from outside the class. This is a good practice to ensure encapsulation.
2. Constructor: The constructor initializes the `value` field when an object of `MutableString` is created.
3. Getter Method: The `getValue()` method allows you to retrieve the current value of the `value` field.
4. Setter Method: The `setValue()` method allows you to change the value of the `value` field after the object is created.
For example:
Let’s see how this class works in practice:
public class Main {
public static void main(String[] args) {
// Create an object of MutableString
MutableString mutableString = new MutableString("Hello");
// Print the initial value
System.out.println("Initial Value: " + mutableString.getValue());
// Modify the value using the setter method
mutableString.setValue("World");
// Print the updated value
System.out.println("Updated Value: " + mutableString.getValue());
}
}
You can also try this code with Online Java Compiler
In this example, we created a `MutableString` object with the initial value `"Hello"`. Later, we changed the value to `"World"` using the `setValue()` method. This demonstrates the mutability of the class.
Immutable Objects
An immutable object is an object whose state cannot be changed after it is created. The String class in Java is immutable, meaning any modification creates a new string object instead of changing the existing one.
Example
public class ImmutableStringExample {
public static void main(String[] args) {
String str = "Hello";
System.out.println("Before modification: " + str);
str = str.concat(" World");
System.out.println("After modification: " + str);
}
}
You can also try this code with Online Java Compiler
Before modification: Hello
After modification: Hello World
Explanation:
The original string "Hello" remains unchanged.
A new string "Hello World" is created and assigned to str, while the old string is discarded.
How to Create an Immutable Class
An immutable class in Java is one where the state (or data) of the object cannot be changed after it is created. Once an object of an immutable class is created, its fields remain constant throughout its lifetime. Immutable classes are useful when you want to ensure that the data remains unchanged, which can help in writing thread-safe & bug-free code.
To create an immutable class, you need to follow these steps:
1. Define the class as final: This prevents the class from being extended.
2. Make all fields private & final: This ensures that the fields cannot be modified after initialization.
3. Do not provide setter methods: Since the fields are final, they cannot be modified, so no setter methods are needed.
4. Initialize all fields through a constructor: This ensures that the fields are set only once during object creation.
5. Return a copy of mutable fields: If the class has mutable fields (like arrays or collections), return a copy of them instead of the actual reference to prevent external modification.
Let’s create a simple immutable class called `ImmutableString`. This class will have a single field called `value` to store a string.
// Step 1: Define the class as final
public final class ImmutableString {
// Step 2: Make the field private & final
private final String value;
// Step 3: Initialize the field through a constructor
public ImmutableString(String value) {
this.value = value;
}
// Step 4: Provide a getter method to access the field
public String getValue() {
return value;
}
// Optional: Override toString() for better readability
@Override
public String toString() {
return "ImmutableString{" +
"value='" + value + '\'' +
'}';
}
}
You can also try this code with Online Java Compiler
1. Final Class: The class is marked as `final` to prevent inheritance. This ensures that no subclass can override its behavior & make it mutable.
2. Private & Final Field: The `value` field is private & final, meaning it cannot be accessed directly or modified after initialization.
3. Constructor: The constructor initializes the `value` field when an object of `ImmutableString` is created.
4. Getter Method: The `getValue()` method allows you to retrieve the current value of the `value` field. Since the field is final, it cannot be modified.
For example:
Let’s see how this class works in practice:
public class Main {
public static void main(String[] args) {
// Create an object of ImmutableString
ImmutableString immutableString = new ImmutableString("Hello");
// Print the value
System.out.println("Value: " + immutableString.getValue());
// Attempting to modify the value will result in a compilation error
// immutableString.setValue("World"); // This line will cause an error
}
}
You can also try this code with Online Java Compiler
In this example, we created an `ImmutableString` object with the value `"Hello"`. Since the class is immutable, there is no way to change the value of the `value` field after the object is created. Any attempt to modify the value will result in a compilation error.
Mutable & Immutable Class Examples
Mutable Class Example
class MutableClass {
private StringBuilder name;
public MutableClass(String name) {
this.name = new StringBuilder(name);
}
public void setName(String name) {
this.name.replace(0, this.name.length(), name);
}
public String getName() {
return name.toString();
}
public static void main(String[] args) {
MutableClass obj = new MutableClass("John");
System.out.println("Before: " + obj.getName());
obj.setName("Alice");
System.out.println("After: " + obj.getName());
}
}
You can also try this code with Online Java Compiler
ImmutableClass is declared as final, preventing subclassing.
The name variable is declared as final, ensuring it cannot be modified after assignment.
No setter method is provided, keeping the object immutable.
Key Differences
Feature
Mutable String (StringBuilder, StringBuffer)
Immutable String (String)
Modification
Allowed, modifies the same object
Not allowed, creates a new object
Memory Efficiency
More efficient, no extra object creation
Less efficient, new objects created
Performance
Faster for modifications
Slower for frequent modifications
Thread Safety
StringBuffer is thread-safe, StringBuilder is not
String is thread-safe
Advantages and Uses of Mutable & Immutable Objects
Mutable Objects
Efficient for frequent modifications: Avoids unnecessary object creation.
Used in string manipulation operations: Useful in cases like file reading and writing, database queries, and large text processing.
Better performance in loops: When modifying strings inside loops, StringBuilder improves efficiency.
Immutable Objects
Security: Prevents unintended modifications, making them useful in security-sensitive applications.
Thread Safety: Since they cannot be modified, immutable objects do not require synchronization in multi-threaded environments.
Caching: Frequently used immutable objects can be cached to improve performance (e.g., String literals in Java).
Frequently Asked Questions
Why is String immutable in Java?
String is immutable for security, thread safety, and efficient memory management. It allows Java to optimize performance by reusing string literals.
When should I use StringBuilder or StringBuffer?
Use StringBuilder when performance is a priority and single-threaded execution is involved. Use StringBuffer when multiple threads need access to the same object.
Can we create a mutable version of String?
Yes, we can use StringBuilder or StringBuffer to create mutable string objects in Java.
Conclusion
In this article, we learned mutable and immutable objects in Java. Mutable objects allow modifications after creation, while immutable objects remain unchanged once initialized. Classes like String are immutable, whereas StringBuilder is mutable. Understanding these concepts is crucial for memory management, thread safety, and performance optimization in Java applications.