A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://www.geeksforgeeks.org/java/how-to-create-immutable-class-in-java/ below:

How to Create Immutable Class in Java?

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 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

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.



RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4