Kotlin приучает нас к
val: "если переменная не меняется — сделай её immutable". Это правильно, но есть нюанс: val не гарантирует неизменяемость объекта, а только то, что ссылка не переназначится.На практике это может привести к багам, особенно при работе с
MutableList, var - свойствами в data-классах, или в многопоточном коде.💥 Пример проблемы:
val items = mutableListOf("A", "B")
items.add("C") // OK, но items всё ещё val
Вроде бы
val, значит безопасно? Нет — items мутируются. Это особенно критично, если вы:- передаёте
val в другие слои архитектуры;- работаете с кэшем или shared state;
- делаете
val глобальными или синглтонами.🧠 Хуже в многопоточке:
class Cache {
val data = mutableMapOf<String, Any>()
}
Если доступ к
data не синхронизирован — ловите гонки. А val создаёт ложное ощущение защищённости.✅ Как писать безопаснее:
- Используйте
List, Map (immutable интерфейсы), а не MutableList, MutableMap, если нет необходимости в мутации.
val items: List<String> = listOf("A", "B")
- Если нужно менять данные — лучше явно использовать
var, чтобы было видно, что объект изменчив.
var state = State()
- Для shared state — применяйте
StateFlow, Mutex, atomic -типы и пр. инструменты контроля доступа.🧵 Ещё пример — data class:
data class User(var name: String)
val user = User("Alice")
user.name = "Bob" // mutable, хотя user — val
Снаружи кажется, что
user не меняется. Но его внутренности - легко. В больших командах это ведёт к багам.⚠️ Вывод
val — это про неизменность ссылки, не объекта. Не полагайтесь на val как на гарантию иммутабельности. Будьте явными в намерениях: или делайте объект действительно immutable, или давайте понять, что он может меняться.✍️ @kotlin_lib