Immutable class in java
We can create immutable classes by following these guidelines:
- Declare the class as
final
, so it cannot be subclassed. - Make all fields
private
andfinal
, so they cannot be modified after initialization. - Do not provide any setters for the fields.
- Initialize all fields via constructor only, and make sure to deep-copy any mutable objects.
- If the class has any mutable objects as fields, return a copy of those objects instead of the original in getter methods.
- Make sure the class is thread-safe.
An example of an immutable class:
public final class Person {
private final String name;
private final int age;
private final List<String> hobbies;
public Person(String name, int age, List<String> hobbies) {
this.name = name;
this.age = age;
this.hobbies = new ArrayList<>(hobbies);
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public List<String> getHobbies() {
return new ArrayList<>(hobbies);
}
}
In this example, the Person
class has three fields: name
, age
, and hobbies
. All fields are private
and final
, and there are no setters provided for any of them. The hobbies
field is an ArrayList
, which is mutable, so we create a new ArrayList
object in the constructor and copy the contents of the original list into it.
The getName
and getAge
methods simply return the value of their respective fields. The getHobbies
method returns a copy of the hobbies
field to prevent modification of the original list.
By following these guidelines, we can ensure that instances of the Person
class are immutable and thread-safe.
Handling Mutable field in an Immutable class:
If the Person
class has a mutable field such as Address
, we need to take additional steps to ensure the immutability of the class. Here are some guidelines to follow:
- Declare the
Address
field asfinal
and create a copy of it in the constructor to ensure that the instance variable is also immutable. - If
Address
has its own mutable fields, such asList
orMap
, create a copy of those fields as well in the constructor. - Return a copy of the
Address
object in the getter method to prevent modification of the original object.
An example of how to modify the Person
class to handle a mutable field Address
:
public final class Person {
private final String name;
private final int age;
private final Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = new Address(address.getStreet(), address.getCity(), address.getState(), new ArrayList<>(address.getHobbies()));
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Address getAddress() {
return new Address(address.getStreet(), address.getCity(), address.getState(), new ArrayList<>(address.getHobbies()));
}
}
In this example, the Person
class has an Address
field, which has its own mutable field hobbies
. To ensure immutability of the Person
class, we create a new Address
object in the constructor by copying the fields of the original Address
object, including a new ArrayList
object to copy the hobbies
field. Similarly, in the getAddress()
method, we return a copy of the Address
object to prevent modification of the original object.
By following these guidelines, we can ensure that instances of the Person
class are fully immutable and thread-safe, even if they contain mutable fields.
Advantages of immutable class:
There are several advantages of immutable classes in Java, including:
- Thread-safety: Immutable objects are inherently thread-safe since they cannot be modified after creation, making them ideal for use in multi-threaded environments.
- Security: Immutable objects cannot be modified by malicious code, preventing unexpected or unauthorized changes to data.
- Simplified code: Immutable classes can simplify code by eliminating the need for defensive copying of objects.
- Better performance: Immutable objects can be cached, shared, and reused, leading to better performance by reducing the need for object creation.
- Ease of testing: Immutable classes are easier to test since their state is fixed and cannot change during runtime, making it easier to write predictable and reliable tests.
- Consistency: Immutable classes enforce consistency, which can be useful in cases where you want to ensure that an object is created with a specific set of values that cannot be changed.
In summary, immutable classes provide a number of benefits that can make our code more secure, reliable, and efficient. By ensuring that objects cannot be modified after creation, immutable classes can improve thread-safety, simplify code, improve performance, and make it easier to test and maintain our code.
Thanks, before you go:
- 👏 Please clap for the story and follow the author 👉
- Please share your questions or insights in the comments section below. Let’s help each other and become better Java developers.
- Let’s connect on LinkedIn