ProgrammingAndroid Developer

How is immutability of objects implemented in Kotlin and how does it differ from Java? Provide examples of correct and incorrect approaches, and explain possible nuances of working with immutable objects.

Pass interviews with Hintsage AI assistant

Answer.

In Kotlin, immutability usually means that the state of an object cannot be changed after it is created. This is achieved through the use of val (immutable) properties, as well as by creating classes that are initialized only in the constructor without methods to modify internal data.

Kotlin, unlike Java, offers a convenient mechanism for creating immutable classes via data class and collections like List, Set, Map (which are immutable by default). However, it's important to understand that the basic collections in Kotlin are immutable at the interface level only, while the collection object itself can be changed if cast to MutableList, etc.

Example of correct immutability:

// Data class and val ensure immutability data class User(val name: String, val age: Int) val user = User(name = "Ivan", age = 30) // user.name = "Sergey" // COMPILATION ERROR

Example of code violating immutability:

class User(var name: String, var age: Int) val user = User("Ivan", 30) user.name = "Sergey" // Object modification is possible

Nuances:

  • Even a data class with val fields does not guarantee complete immutability if the fields are reference types and their internal state changes.
  • For true immutability, use only val + immutable types (e.g., val scores: List<Int>).

Trick Question.

Are objects of a data class with only val properties completely immutable?

Answer: No, if the properties are mutable objects (e.g., val items: MutableList<Int>), the internal state can be changed.

Example:

data class Group(val members: MutableList<String>) val group = Group(mutableListOf("Tom", "Jerry")) group.members.add("Spike") // internal state is changing

Examples of real errors due to ignorance of the topic.


Story

An immutable data class with a val property of type MutableList was used in the project. One developer expected that the object could not be modified, however, another developer added new elements to the collection. This led to data inconsistency and hard-to-detect bugs when two threads modified a shared list simultaneously.


Story

When passing an instance of a class with a mutable collection between application layers, one layer modified the contents without notifying the other layer. This caused situations where the UI was unaware of the changes and worked with invalid initial data.


Story

A developer mistakenly believed that List in Kotlin is always immutable. In fact, an implementation passed from Java (ArrayList) was used under the hood, and attempts to modify the list led to unexpected data loss and bugs when interacting with the database.