Popular Feed

How to create an Immutable class in Java?

How to create an Immutable class in Java?

Class should be final, so that no other classes can extend it.

All your fields final, so that they’re initialized only once inside the constructor and never modified afterward.

Don’t expose setter methods.

When exposing methods which modify the state of the class, you must always return a new instance of the class.

Find the below code to create an immutable class.


final class ImmutableStudent {
    private final int id;
    private final String name;
    public ImmutableStudent(int id, String name) {
        this.name = name;
        this.id = id;
    }
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
}
public class Loops {
	public static void main(String[] args) {
		ImmutableStudent s = new ImmutableStudent(101,"abc"); 
		System.out.println(s.getName()); 
		System.out.println(s.getId()); 
		//s.name = "xyz"; // line 20
	}
}
in line 20 we will get the compilation error because we cannot change the final value once assigned.

But there is a problem if we inject(use) the mutable class inside immutable class.

package test.demo;


class Age {
	private int day;
	private int month;
	private int year;
	public int getDay() {
		return day;
	}
	public void setDay(int day) {
		this.day = day;
	}
	public int getMonth() {
		return month;
	}
	public void setMonth(int month) {
		this.month = month;
	}
	public int getYear() {
		return year;
	}
	public void setYear(int year) {
		this.year = year;
	}
}
final class ImmutableStudent {
	private final int id;
	private final String name;
	private final Age age;
	public ImmutableStudent(int id, String name, Age age) {
		this.name = name;
		this.id = id;
		this.age = age;
	}
	public int getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public Age getAge() {
		return age;
	}
}
public class Loops {
	public static void main(String[] args) {
		Age age = new Age();
		age.setDay(1);
		age.setMonth(1);
		age.setYear(1992);
		ImmutableStudent student = new ImmutableStudent(1, "Alex", age);
		System.out.println("Alex age year before modification = " + 
                   student.getAge().getYear());
		age.setYear(1993);
		System.out.println("Alex age year after modification = " + 
                   student.getAge().getYear());
	}
}
Output :
Alex age year before modification = 1992
Alex age year after modification = 1993

so as you can see we are able to change the year of students. This breaks the immutability of class student.

So how we can fix this?
so we need to change the constructor of student class. We need to create a new object inside the student constructor. Find below code.

public ImmutableStudent(int id, String name, Age age) {
    this.name = name;
    this.id = id;
    Age cloneAge = new Age();
    cloneAge.setDay(age.getDay());
    cloneAge.setMonth(age.getMonth());
    cloneAge.setYear(age.getYear());
    this.age = cloneAge;
}
Output:
Alex age year before modification = 1992 Alex age year after modification = 1992

But hold one there is still a problem with this code.

public static void main(String[] args) {
		Age age = new Age();
		age.setDay(1);
		age.setMonth(1);
		age.setYear(1992);
		ImmutableStudent student = new ImmutableStudent(1, "Alex", age);
		System.out.println("Alex age year before modification = " + 
                     student.getAge().getYear());
		student.getAge().setYear(1993);
		System.out.println("Alex age year after modification = " + 
                     student.getAge().getYear());
	}
If you run above code you will get below output.

Alex age year before modification = 1992 Alex age year after modification = 1993

We are getting the age object from student object and than we are modifying it.
Use below code to correct the issue.

public Age getAge() {
		Age cloneAge = new Age();
		cloneAge.setDay(this.age.getDay());
		cloneAge.setMonth(this.age.getMonth());
		cloneAge.setYear(this.age.getYear());
		return cloneAge;
	}
So while getting age object from student we should give the same object which we have created at the time of student object construction. That is why we are creating an object and assigning the same values.






No comments: