ProgrammingJava Developer

What are immutable objects in Java, what is their value, and how to correctly implement your own immutable class?

Pass interviews with Hintsage AI assistant

Answer.

Immutable objects are objects whose state cannot be modified after creation. Their main properties are:

  • All fields are final;
  • They do not contain setters;
  • It is not possible to obtain a mutable reference to any internal objects (e.g., collections).

Advantages of immutable objects:

  • Safe for multithreaded access (thread-safe);
  • Easy to cache and reuse as keys in collections;
  • Simplifies debugging and testing;
  • Fewer bugs due to unexpected state changes.

Example of an immutable class implementation:

public final class Person { private final String name; private final int age; private final List<String> phones; public Person(String name, int age, List<String> phones) { this.name = name; this.age = age; // Protection against mutation of the passed list this.phones = Collections.unmodifiableList(new ArrayList<>(phones)); } public String getName() { return name; } public int getAge() { return age; } public List<String> getPhones() { return phones; } // Return a read-only list }

Trick question.

Why is String in Java immutable and what would happen if it were not? Many answer "for safety", but what does that mean in practice?

Answer:

String is used in many places: as keys in collections, in security logic (for example, passwords). If a string could be changed through one reference, it would affect all other references to the same object, making the correct functioning of collections impossible (e.g., HashMap — when calculating hashCode) and could lead to security vulnerabilities.

Examples of real errors due to ignorance of the nuances of the topic.


Story

In a large banking project, internal collections (list of transactions) were passed using a regular getter. As a result, the list could be modified from outside, breaking invariants (e.g., adding a transaction with an incorrect date). This led to data loss until they started returning Collections.unmodifiableList.

Story

In the root configuration class, unprotected field-objects (Date, List) were stored. In one thread, the configuration was modified, and in another, outdated or inconsistent data was obtained, causing the business algorithm to malfunction.

Story

In a login system, passwords were stored in a mutable object. Through unsafe access, another user's password "leaked" unexpectedly, as the same instance of the object was used by many threads.