To create an immutable class in Java, you need to follow a few key principles:
1. Make the Class Final
Declare the class as final
to prevent inheritance. This ensures that no subclasses can modify the class's behavior.
public final class ImmutableClass {
// ...
}
2. Make All Fields Private and Final
Declare all fields as private
and final
. This prevents direct access and modification of the fields from outside the class.
public final class ImmutableClass {
private final String name;
private final int age;
// ...
}
3. Provide a Constructor to Initialize Fields
Use a constructor to initialize all fields upon object creation. This ensures that the values are set only once and cannot be changed later.
public final class ImmutableClass {
private final String name;
private final int age;
public ImmutableClass(String name, int age) {
this.name = name;
this.age = age;
}
// ...
}
4. Do Not Provide Setter Methods
Avoid creating any methods that modify the state of the object. This ensures that the object remains unchanged after creation.
public final class ImmutableClass {
// ...
// No setter methods like setName() or setAge()
}
5. Return Defensive Copies of Mutable Fields
If any fields are mutable (e.g., lists, maps), return defensive copies of them in getter methods to prevent external modifications.
public final class ImmutableClass {
private final List<String> hobbies;
public ImmutableClass(String name, int age, List<String> hobbies) {
// ...
this.hobbies = new ArrayList<>(hobbies); // Defensive copy
}
public List<String> getHobbies() {
return new ArrayList<>(hobbies); // Return a copy
}
}
Example
Here's a complete 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);
}
}
By following these principles, you can create immutable classes in Java, ensuring that their state remains unchanged after creation. This can lead to simpler code, improved thread safety, and easier reasoning about object behavior.