How to Create Immutable Class in Java?
Last Updated :
30 May, 2025
In Java, immutability means that once an object is created, its internal state cannot be changed. Immutable classes in Java provide many advantages like thread safety, easy debugging and all. In Java, all the wrapper classes (like Integer, Boolean, Byte, Short) and the String class is immutable. We can create our own immutable class as well.
In this article, we are going to learn:
- What immutability means
- Why it is useful
- How to create our own immutable class
- Why deep copying is important
- What are the limitations Java record types have
What is an Immutable Class?
An immutable class is a class whose objects cannot be changed once created. If we do any modification, it results in a new object. This method is used in concurrent applications.
Rules for Creating an Immutable Class
- The class must be declared as final so that child classes cannot be created.
- Data members in the class must be declared private so that direct access is not allowed.
- Data members in the class must be declared as final so that we can’t change their value after object creation.
- A parameterized constructor should initialize all the fields, performing a deep copy so that data members can't be modified with an object reference.
- Deep Copy of objects should be performed in the getter methods to return a copy rather than returning the actual object reference.
Note: There should be no setters or in simpler terms, there should be no option to change the value of the instance variable.
Example: Immutable class implementation
Student.java
Java
// Java Program to Create An Immutable Class
import java.util.HashMap;
import java.util.Map;
// declare the class as final
final class Student {
// make fields private and final
private final String name;
private final int regNo;
private final Map<String, String> metadata;
// initialize all fields via constructor
public Student(String name, int regNo, Map<String, String> metadata) {
this.name = name;
this.regNo = regNo;
// deep copy of mutable object (Map)
Map<String, String> tempMap = new HashMap<>();
for (Map.Entry<String, String> entry : metadata.entrySet()) {
tempMap.put(entry.getKey(), entry.getValue());
}
this.metadata = tempMap;
}
// only provide getters (no setters)
public String getName() {
return name;
}
public int getRegNo() {
return regNo;
}
// return deep copy to avoid exposing internal state
public Map<String, String> getMetadata() {
Map<String, String> tempMap = new HashMap<>();
for (Map.Entry<String, String> entry : this.metadata.entrySet()) {
tempMap.put(entry.getKey(), entry.getValue());
}
return tempMap;
}
}
In this example, we have created a final class named Student. It has three final data members, a parameterized constructor, and getter methods. Please note that there is no setter method here. Also, note that we don't need to perform deep copy or cloning of data members of wrapper types as they are already immutable.
Geeks.java:
Java
import java.util.HashMap;
import java.util.Map;
public class Geeks {
public static void main(String[] args) {
// create a map and adding data
Map<String, String> map = new HashMap<>();
map.put("1", "first");
map.put("2", "second");
// create an immutable Student object
Student s = new Student("GFG", 101, map);
// accessing data
System.out.println(s.getName());
System.out.println(s.getRegNo());
System.out.println(s.getMetadata());
// try to modify the original map
map.put("3", "third");
System.out.println(s.getMetadata());
// try to modify the map returned by getMetadata()
s.getMetadata().put("4", "fourth");
System.out.println(s.getMetadata());
}
}
Even after modifying the original or returned Map, the internal state of the Student object remains unchanged. This confirms the immutability concept.
Output:
GFG
101
{1=first, 2=second}
{1=first, 2=second}
{1=first, 2=second}
Limitation of Java record with Mutable Fields
Java 14 introduced record. This is a clear and concise way to define immutable like classes:
record Student(String name, int regNo, Map<String, String> metadata) {}
But this only offers shallow immutability. If the Map is modified externally, the internal state of the record changes:
Map<String, String> map = new HashMap<>();
map.put("1", "first");
Student s = new Student("ABC", 101, map);
// Changes internal state — NOT safe
map.put("2", "second");
s.metadata().put("3", "third");
Note: Use record only if all fields are immutable types like String, int, or other records.
Similar Reads
How to Create Custom Class in Java? Class is the collection of objects. Class is not a real-world entity it is just only templates and prototypes or blueprints. Class does not occupy memory. We can write a custom class as per our choice for an illustration purpose a sample is shown in the program below as a helper class. Example: Java
2 min read
How to Import Custom Class in Java? Java language is one of the most popular languages among all programming languages. There are several advantages of using the java programming language, whether for security purposes or building large distribution projects. One of the advantages of using Java is that it tries to connect every concep
3 min read
Factory method to create immutable Map in Java 9 In Java 9 there are some features are added in Java language and factory method for immutable map is one of them. Characteristics of immutable map: As the name suggest these map are immutable. If any attempt made to add, delete and update elements in the map we will have UnsupportedOperationExceptio
3 min read
Factory method to create Immutable Set in Java 9 Java 9 was released around march 2017 and please install jdk 9, it will be helpful in understanding the code used in this article. In Java 9, there are some features added in Java language and factory method for immutable Set is one of them. So lets get started! Characteristics of Immutable Set: As
3 min read
Factory method to create Immutable List in Java SE 9 Java 9 was released around march 2017 and In Java 9 there are some features are added in Java language and factory method for immutable List is one of them. Characteristics of Immutable List: As the name suggest these lists are immutable. If any attempt made to add, delete and update elements in the
3 min read
Immutable Set in Java As the name suggest these Set are immutable. If any attempt made to add, delete and update elements in the set we will have UnsupportedOperationException. An ImmutableSet does not allow null element either. If any attempt made to create an ImmutableSet with null element, we will have NullPointerExce
3 min read
Immutable List in Java ImmutableList, as suggested by the name, is a type of List which is immutable. It means that the content of the List are fixed or constant after declaration, that is, they are read-only. If any attempt made to add, delete and update elements in the List, UnsupportedOperationException is thrown. An I
5 min read
Primitive Wrapper Classes are Immutable in Java In Java, an immutable class is a class (Integer, Byte, Long, Float, Double, Character, Boolean, and Short) which once created then its body can not be changed and the same applies to immutable objects which once created cannot be changed. Now the question arises that we do need the help of wrapper c
3 min read
Immutable Map in Java ImmutableMap, as suggested by the name, is a type of Map which is immutable. It means that the content of the map are fixed or constant after declaration, that is, they are read-only.If any attempt made to add, delete and update elements in the Map, UnsupportedOperationException is thrown.An Immutab
6 min read
Collecting a Stream to an Immutable Collection in Java Streams and Collectors were introduced in Java 8 introduced the concept of Streams. A Stream is a sequence, a sequence of objects. We generate Streams from input sources like Arrays, Lists, etc., and support aggregation operations like filter, map, limit, reduce, etc. We use Streams to pipeline data
6 min read