Mutable and Immutable Objects in Java
Java is a popular object-oriented programming (OOP) language and it's code design revolves around it's objects and their manipulation. One of the key concepts in this OOP paradigm is the classification of objects into mutable and immutable types. These classifications say whether an object's state can be modified after its creation or not. This is very important concept to understand the behavior and design of Java programs.
Pre-requisite: Object Oriented Programming (OOPs) Concept in Java
Note: In this article, an object's state at a particular instant means the snapshot of all of the values of that object's data members (or fields) at that particular point of time.
This article explains the definition, example, code, comparison, and advantages of Mutable and Immutable Objects in Java.
Mutable Objects
Mutable class objects are those whose state can be modified after initialization. This means the values of their fields can be changed, add or remove elements from the collections they contain, ie generally alter their internal state. Examples of mutable objects are Java's StringBuilder, StringBuffer, & java.util.Date.
In mutable objects, changes to the object's state (data members) do not result in the creation of a new object. Instead, the existing object's values are modified through functions provided by the object's class, such as setters. Mutable objects have both getters and setters functions.
Immutable Objects:
On the other hand, immutable class objects are those whose state cannot be modified after initialization. Once created, the values and state of an immutable object remain fixed throughout its scope. Examples of immutable objects are primitive types like int, long, float, double, as well as classes like String. all legacy classes and wrapper classes are Immutable classes.
Immutable objects, by their nature, do not provide methods/functions to modify their state. Instead, they only offer getters to retrieve their values and no setters function. Any attempt to change an immutable object's state results in the creation of a new object with the modified values.
Mutable & Immutable Class examples
Mutable class:
Mutable class coding:
- Encapsulate mutable fields: Keep access modifiers of all data fields (or attribute/members) as private and provide modification access through getter and setter functions only.
- Synchronize access: Use synchronization mechanisms if the object will be accessed by multiple threads to avoid race conditions.
- If mutable class objects is stored in a collection type, it should be carefully ensured that the collection's contract doesn't allow modification of objects outside of the code's control.
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String newName) {
this.name = newName;
}
public static void main(String[] args) {
Person person = new Person("John");
System.out.println(person.getName());
person.setName("Doe");
System.out.println(person.getName());
}
}
Output
John Doe
Immutable class code:
- All mutable data fields should be private and final so that fields once initialized, cannot be directed accessed, modified or iterated.
- No setter methods in Class to avoid functions that modify the object's state.
- If immutable class object contains mutable fields (like arrays or collections), return defensive copies to maintain immutability.
- Make the Final class, (declared as final) so that it can't be extended.
public final class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public static void main(String[] args) {
Point point = new Point(5, 10);
System.out.println("X: " + point.getX() + ", Y: " + point.getY());
}
}
Output
X: 5, Y: 10
Key Differences:
- Mutable class objects allow changes to their state after initialization, while immutable class objects do not.
- Mutable class objects provide methods to modify their content, whereas immutable class objects do not allow state modification.
- Mutable class objects may or may not be thread-safe, while immutable class objects are inherently thread-safe.
- Creating a new object is required when modifying the state of an immutable class object, while mutable class objects are modified in place.
Here are summary of important differences.
Mutable | Immutable |
---|---|
can change the value of the object after initialization. | cannot change the values of object after initialization |
State can be changed | State remains constant after creation |
No new objects are formed | Changing the value of the object creates a new object |
Provides methods to change object | Does not provide methods to change object value |
Supports get() and set() methods | Only supports get() method to retrieve object value |
May or may not be thread-safe | Immutable objects are inherently thread-safe |
Essentials for creating a mutable class include methods for modifying fields, getters, and setters | Essentials for creating an immutable class include final class, private fields, and final mutable objects |
Advantages and Uses of Mutable & Immutable Object
Mutable Objects Advantages | Immutable Objects Advantages |
---|---|
Flexibility: Mutable class objects allow modification of their state, which is useful for dynamic changes. | Thread Safety: Immutable objects can be shared across threads without synchronization since their state cannot change. |
Performance: Often perform well since they can be modified directly without creating new objects. | Security: Immutable objects are more secure as their state cannot be altered maliciously after creation. |
Builder Pattern: Mutable objects are commonly used with the builder pattern, allowing fluent and readable object creation. | Simpler State Management: Immutable objects simplify debugging and maintenance because their state does not change unexpectedly. |
Caching: Ideal for caching mechanisms as their state does not change, making them easily cacheable. | |
Memory Management: Easier memory management since they do not require defensive copying. |