Sobes.tech
Middle

Why are immutable classes needed and what are their main characteristics?

sobes.tech AI

Answer from AI

Immutable classes are classes whose objects cannot be changed after creation. All their fields are declared as final and initialized once in the constructor(s).

Main characteristics:

  • Thread-safety: Objects are inherently thread-safe because their state never changes. No synchronization is required to work with them.
  • Simplicity: They are easier to design, implement, and use because there is no need to worry about state changes. This reduces the number of errors.
  • Caching: Such objects can be safely used as keys in a Map or elements in a Set, since their hash code and equality (defined by the equals method) do not change.
  • Safety: Using immutable objects prevents unwanted side effects when one part of the code modifies an object used in another part.
  • Sharing: Multiple references can point to the same immutable object without the risk of changing its state.

Example:

public final class ImmutablePoint { // 1. Final class
    private final int x; // 2. Final fields
    private final int y;

    public ImmutablePoint(int x, int y) { // 3. Initialization in constructor
        this.x = x;
        this.y = y;
    }

    public int getX() { // 4. No setters
        return x;
    }

    public int getY() {
        return y;
    }

    // Optional: override equals() and hashCode()
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ImmutablePoint that = (ImmutablePoint) o;
        return x == that.x && y == that.y;
    }

    @Override
    public int hashCode() {
        return 31 * x + y;
    }

    // Optional: create new objects for "modified" states
    public ImmutablePoint translate(int dx, int dy) {
        return new ImmutablePoint(x + dx, y + dy);
    }
}

If the class contains mutable objects as fields, to ensure immutability, it is necessary to make copies of them when passing to the constructor and when returning through getters (deep copy).