Make immutable Java object
JavaImmutabilityJava Problem Overview
My goal is to make a Java object immutable. I have a class Student
. I coded it in the following way to achieve immutability:
public final class Student {
private String name;
private String age;
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
My question is, what is the best way to achieve immutability for the Student
class?
Java Solutions
Solution 1 - Java
Your class is not immutable strictly speaking, it is only effectively immutable. To make it immutable, you need to use final
:
private final String name;
private final String age;
Although the difference might seem subtle, it can make a significant difference in a multi-threaded context. An immutable class is inherently thread-safe, an effectively immutable class is thread safe only if it is safely published.
Solution 2 - Java
There are few things that you must consider for making an immutable class:
- Make your class
final
- You already have - Make all the fields
private
andfinal
- Make appropriate changes in your code - Don't provide any methods that change the state of your instance
- If you have mutable fields in your class, like
List
, orDate
, making themfinal
won't suffice. You should return a defensive copy from theirgetters
, so that their state isn't mutated by calling methods.
For the 4th point, say you have a Date
field in your class, then the getter for that field should look like:
public Date getDate() {
return new Date(this.date.getTime());
}
Making a defensive copy can become a headache, when your mutable field itself comprises of some mutable field, and that in turn can contain some other mutable field. In that case, you would need to make copy of each of them iteratively. We name this iterative copy of mutable fields as Deep Copy.
Implementing deep copy by yourself may be cumbersome. But,keeping that issue apart, you should consider your class design again, once you see yourself falling into such requirement of making deep defensive copy.
Solution 3 - Java
> How do you make a mutable object immutable?
- Declare the class as final so it can’t be extended.
- Make all fields private so that direct access is not allowed.
- Don’t provide setter methods for variables
- Make all mutable fields final so that it’s value can be assigned only once.
- Initialize all the fields via a constructor performing deep copy.
- Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference.
>Why do we create immutable objects?
>Immutable objects are simply objects whose state (the object's data) cannot change after construction.
- Security: store sensitive pieces of information like usernames, passwords, connection URLs, network connections etc.
- are simple to construct, test, and use
- are automatically thread-safe and have no synchronization issues
- don't need a copy constructor
- don't need an implementation of clone
- allow hashCode to use lazy initialization, and to cache its return value
- don't need to be copied defensively when used as a field
- make good Map keys and Set elements (these objects must not change state while in the collection)
- have their class invariant established once upon construction, and it never needs to be checked again
- always have "failure atomicity" (a term used by Joshua Bloch): if an immutable object throws an exception, it's never left in an undesirable or indeterminate state
In Java, Strings are immutable, which provides, such as caching, security, easy reuse without replication, etc. Source
Solution 4 - Java
With final
keyword:
private final String name;
private final String age;
Solution 5 - Java
Making variables private and no setter methods will work for primitive data types. If my class has any collection of objects?
To making any class immutable with collection object?
Write your own collection object with extends collection class and follow the private variables and no setter methods. or return clone object of your collection object.
public final class Student {
private StudentList names;//Which is extended from arraylist
public Student() {
names = DAO.getNamesList()//Which will return All Student names from Database its upto you how you want to implement.
}
public StudentList getStudentList(){
return names;//you need to implement your own methods in StudentList class to iterate your arraylist; or you can return Enumeration object.
}
public Enumeration getStudentNamesIterator(
Enumeration e = Collections.enumeration(names);
return e;
}
public class StudentList extends ArrayList {
}
Solution 6 - Java
This is fine but I would make the fields final
as well.
Also I would make the age an int
or double
rather than a String.
Solution 7 - Java
Expanding on the answer a bit.
final
is not the same as Immutable
but you can use final
to make certain things immutable if you use it in certain ways.
Certain types are immutable, in that they represent unchanging values rather than objects of changeable state. Strings, numbers, etc are immutable. At the end, usually our objects boil down to data structures eventually referencing immutable values, but we change the data structures by assigning new values to the same field names.
So to make something truly immutable you need to make sure that final is used all the way down, until you reach every field reaching every value at the base of your composition tree. Otherwise something could change out from under your the object and it isn't really fully immutable.
Solution 8 - Java
Your example is already immutable object, because fields in Student class can only set on instance initialization.
To make object immutable, You must do these steps:
- Don't use any methods, which can change fields of your class. For example don't use Setters.
- Avoid to use public non-final fields. If your fields is public then you must declare them as final and initialize them in constructor or directly in the declaration line.
Solution 9 - Java
It is too late to answer but may be it help other peoples who have this question.
- State of immutable object can not be modified after construction, any modification should result in new immutable object.
- All fields of Immutable class should be final.
- Object must be properly constructed i.e. object reference must not leak during construction process.
- Object should be final in order to restrict sub-class for altering immutability of parent class.
I think this link help more Read more: http://javarevisited.blogspot.com/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html#ixzz40VDQDDL1
Solution 10 - Java
It already is immutable -- you can't change the contents once you initialize it, since you haven't made setters. You might add final keywords to the variables.
Solution 11 - Java
Making all variables as final
and when setting some field, making it return the reference to the new Student
object with the newly set value like in String
.
Solution 12 - Java
You can just follow guidelines shown in this example (first result in google): http://www.javapractices.com/topic/TopicAction.do?Id=29
Solution 13 - Java
Here are few rules, which helps to make a class immutable in Java :
- State of immutable object can not be modified after construction, any modification should result in new immutable object.
- All fields of Immutable class should be final.
- Object must be properly constructed i.e. object reference must not leak during construction process.
- Object should be final in order to restrict sub-class for altering immutability of parent class.
Example:
public final class Contacts {
private final String name;
private final String mobile;
public Contacts(String name, String mobile) {
this.name = name;
this.mobile = mobile;
}
public String getName(){
return name;
}
public String getMobile(){
return mobile;
}
}
Refer this link : http://javarevisited.blogspot.in/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html
Solution 14 - Java
According to Strategy for Defining Immutable Objects
-
Don't provide "
setter
" methods — methods that modify fields or objects referred to by fields. -
Make all fields
final
andprivate
. -
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as
final
.a. A more sophisticated approach is to make the
constructor
private and construct instances in factory methods. -
If the instance fields include references to mutable objects, don't allow those objects to be changed:
a. Don't provide methods that modify the mutable objects.
b. Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
Solution 15 - Java
Java SE 16
You can use JEP 395: Records feature, introduced as part of Java SE 16, to create an immutable class in a succinct manner.
If you have already gone through the above link, you must have figured out that you can do it simply as
record Student(String name, String age) { }
What you get in turn are:
- A
final class Student
. - A canonical constructor whose signature is the same as the header,
Student(String name, String age)
. private final
fields,name
andage
and their correspondingpublic
accessor method with the same name and return type.- Automatically created
equals
,hashCode
andtoString
methods.
Demo:
Student.java
record Student(String name, String age) { }
Main.java
class Main{
public static void main(String[] args) {
Student s1 = new Student("Bharat", "10 Years");
Student s2 = new Student("Arvind", "10 Years");
System.out.println(s1);
System.out.println(s1.equals(s2));
System.out.println(s1.age().equals(s2.age()));
}
}
Output:
Student[name=Bharat, age=10 Years]
false
true
Solution 16 - Java
Make the class or variable as final that's more than enough
Public final class constants
{
private final String name;
private final String mobile;
// code
}