Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction 
2.
What is Immutable class in Java?
3.
Create an immutable class in java
3.1.
1. Make the class Final so that it cannot be extended.
3.2.
2. Make all fields private so that direct access is prohibited.
3.3.
3. Don't provide variable setter methods.
3.4.
4. Make all mutual fields final, – this means their values cannot be changed.
3.5.
5. Using deep copy, invoke all fields by constructors.
3.6.
6. Clone objects in getter methods to return a duplicate rather than the original object reference.
4.
Example of Immutable class in Java
5.
What happens when you don’t use deep copy and cloning?
6.
Frequently Asked Questions
6.1.
Can we create our own immutable class?
6.2.
How do you protect an immutable class?
6.3.
Can we break immutable class in Java?
6.4.
Why do we need immutable classes in Java?
7.
Conclusion 
Last Updated: Mar 27, 2024
Medium

How to Create Immutable Class in Java

Author Gaurav Gandhi
0 upvote
Crack Google SDE interview : Essential projects
Speaker
Saurav Prateek
SDE-2 @
20 Jun, 2024 @ 01:30 PM

Introduction 

Before we jump on to answering the question of how to create immutable class in Java, let us define what immutable is in any programming language. An immutable entity (unchangeable object) in object-oriented and functional programming is one whose state cannot be changed after it is created.  In comparison, a mutable object (changeable object) can be modified after it has been created. In some cases, an object appears immutable even if some of its internal attributes change but the object's state would seem unchanged from the outside. 

Immutability is a characteristic that means that it cannot be changed or modified. In this article we will discuss the question of how to create immutable class in java.

how to create immutable class in java

What is Immutable class in Java?

If an object's state cannot change after modification, it is said to be immutable. String and all wrapper classes in Java, for example, are immutable. When we attempt to alter an immutable class, it generates a new object. As a result, immutable objects cannot be modified. The Immutable class in Java states that once an object is created, its content cannot be changed. The final keyword is important while addressing the question of how to create immutable class in java. Wrapper and String classes are all immutable. Let us see an example to understand this concept in more detail.

A string in Java is a class that cannot be modified. If we create a string object and try to assign a new value, a new object is created and it points to the new one.

String city = "Delhi"; 
city = "Chandigarh"; 

The new value of the name is Chandigarh. And the previous one i.e. Delhi, will not be referred to.

immutable class in java
Get the tech career you deserve, faster!
Connect with our expert counsellors to understand how to hack your way to success
User rating 4.7/5
1:1 doubt support
95% placement record
Akash Pal
Senior Software Engineer
326% Hike After Job Bootcamp
Himanshu Gusain
Programmer Analyst
32 LPA After Job Bootcamp
After Job
Bootcamp

Create an immutable class in java

Let's learn how to create a Student immutable class with the following fields: id, name, and subjects:

1. Make the class Final so that it cannot be extended.

public class final Student {
    String studentName;
    Integer studentId;
    List < String > subject;
}

2. Make all fields private so that direct access is prohibited.

public class final Student {
    private String studentName;
    private Integer studentId;
    private List < String > subject;
}

3. Don't provide variable setter methods.

public class final Student {
    private String studentName;
    private Integer studentId;
    private List < String > subject;
    public String getstudentName() {
        return this.studentName;
    }
    public Integer getstudentId() {
        return this.studentId;
    }
    public List < String > getsubject() {
        return this.subject;
    }
}

4. Make all mutual fields final, – this means their values cannot be changed.

public class final Student {
    private String studentName;
    private final Integer studentId;
    private final List < String > subject;
    public String getstudentName() {
        return this.studentName;
    }
    public String getstudentId() {
        return this.studentId;
    }
    public List < String > getsubject() {
        return this.subject;
    }
}

5. Using deep copy, invoke all fields by constructors.

public class final Student {
    private String studentName;
    private final Integer studentId;
    private final List < String > subject;
    public Student(String name, Integr id, List < String > subject) {
        this.studentName = name;
        this.studentId = id;
        this.subject = subject;
    }
    public String getstudentName() {
        return this.studentName;
    }
    public String getstudentId() {
        return this.studentId;
    }
    public List < String > getsubject() {
        return this.subject;
    }
}

6. Clone objects in getter methods to return a duplicate rather than the original object reference.

public class final Student {
    private String studentName;
    private final Integer studentId;
    private final List < String > subject;
    public Student(String name, Integr id, List < String > subject) {
        this.studentName = name;
        this.studentId = id;
        this.subject = subject;
    }
    public String getstudentName() {
        return this.studentName;
    }
    public String getstudentId() {
        return this.studentId;
    }
    public List < String > getsubject() {
        return this.subject.clone();
    }
}


Also see, Java Ioexception

Example of Immutable class in Java

import java.util.LinkedList;
import java.util.List;
public final class Immutable {
    private final int uid;
    private final List < Object > list;
    private String fname;
    public Immutable(int uid, List < Object > list, String fname) {
        super();
        this.uid = uid;
        this.list = list;
        this.fname = nfame;
    }
    public int getUId() {
        return uid;
    }
    public String getName() {
        return fname;
    }
    public List < Object > getList() {
        return new LinkedList < > (list); // defensive
    }
}


Here in this code, we are creating an immutable class: Immutable and we are getting the values using the get method. Now let's give this code the value and change its value again to see if it's giving the same output or not. 

 

import java.util.LinkedList;
import java.util.List;
public class Main {
    public static void main(String[] args) {
        List < Object > lst = new LinkedList < Object > ();
        lst.add("hello");
        lst.add("world");
        Immutable im = new Immutable(46, lst, "Rahul");
        System.out.println(im.getId());
        System.out.println(im.getName());
        System.out.println(im.getList());
        //modify list
        im.getList().add("Raj");
        System.out.println(im.getList()); //remain unchanged
    }
}


If we run this code, we will get the following output and the later given value i.e. Raj will not be displayed. 

46
Rahul
[hello, world]
[hello, world]

 

By this code, we get to see that even if we change the values of the variables, it won't affect them. The initial values will be printed. It shows that even after changing the collection, the values do not change. Try this code on Java Compiler.

What happens when you don’t use deep copy and cloning?

When we don't use deep copy and cloning in Java, we may encounter several problems. These problems can be related to object manipulation, data integrity, and unexpected behavior. There are some common consequences of not using deep copy and cloning:

  • Shared references: If we assign an object to another variable or pass it as an argument to a method, both variables will reference the same object in memory. Any changes made to one variable will directly affect the other variable. It can lead to unintended modifications and potential data corruption.
     
  • Nested object problems: In Java, objects often contain other objects or collections (e.g., arrays, lists). Shallow copying of such objects will only copy the references to the nested objects, not the objects themselves. As a result, modifications to nested objects in one copy will impact all other copies sharing the same reference.
     
  • Inconsistent State: When using shallow copy, the copied object may end up with an inconsistent state, as not all properties are copied deeply. This can lead to unexpected behavior and bugs in your application.
     
  • Security Risks: In scenarios where security is critical, a shallow copy can pose risks. If sensitive data is stored in objects and shared references allow unauthorized access to that data, it can lead to security breaches.
     
  • Memory Management Issues: Shallow copying of objects containing shared references can lead to memory leaks. Garbage collection may not properly release the memory occupied by objects because their references are still in use.

Frequently Asked Questions

Can we create our own immutable class?

Yes, you can create your own immutable class in Java. An immutable class is a class whose objects cannot be modified after creation. Once an immutable object is created, its state remains constant throughout its lifetime. 

How do you protect an immutable class?

To protect an immutable class, the class should be declared as final to prevent any inheritance, ensuring that its behavior remains constant and cannot be altered by subclasses. Then all instance variables (fields) of the class should be declared as private, restricting direct access from outside the class and preventing external code from modifying the fields directly.

Can we break immutable class in Java?

In Java, breaking an immutable class is technically possible but goes against the design principles of immutability. It can be achieved through reflection or other unconventional means, but such practices are generally discouraged as they compromise the integrity and predictability of the class's immutable behavior.

Why do we need immutable classes in Java?

Immutable classes in Java are crucial for creating objects whose state cannot be modified after creation. This immutability ensures thread safety, as concurrent modifications cannot occur. It simplifies development, as immutable objects are predictable and easy to reason about. Additionally, they are inherently safe from cloning, prevent side effects, and are useful for caching and synchronization in multi-threaded applications.

Conclusion 

To conclude this blog, we first discussed what the term immutable means. And how does it fit into the Java programming language? Following that, we looked at how to create immutable class in Java, as well as some interesting examples. Then we talked about some more immutable classes in JDK, and finally, we talked about the benefits of immutable classes.

Recommended Readings:

Refer to our guided paths on Coding Ninjas Studio to upskill yourself in Data Structures and AlgorithmsCompetitive Programming, and many more! If you want to test your competency in coding, you may check out the mock test series and participate in the contests . But if you have just started your learning process and looking for questions asked by tech giants like Amazon, Microsoft, Uber, etc; you must have a look at the problems, and interview experiences for placement preparations.

Nevertheless, you may consider our paid courses to give your career an edge over others!

Previous article
Constant
Next article
Java Extend Multiple Classes
Live masterclass