Как передаются параметры функции в Kotlin, по ссылке или по значению
Что проверяют
Отличаете ли вы передачу ссылки по значению от передачи по ссылке и понимаете ли, что из этого следует для мутабельных объектов. На Android следом часто спрашивают, почему после изменения списка не обновился экран.
Как отвечать
В Kotlin, как и в Java, передача всегда по значению. Для объектов значение это ссылка, поэтому функция получает копию ссылки на тот же объект.
- параметры неизменяемы: параметр функции ведёт себя как
val, кодvalue += 1внутри функции не скомпилируется. Переприсвоить параметр нельзя, поэтому переменная вызывающего кода не поменяется никогда; - мутабельный объект: если передать
MutableListили класс сvar-полями, функция может изменить содержимое, и вызывающий код это увидит; - «примитивы»:
IntиBooleanна JVM компилируются вintиboolean, но в nullable-типе или дженерике упаковываются вInteger. На семантику передачи это не влияет, только на аллокации; - иммутабельные данные:
String,data classсval-полями. Изменение делают возвратом нового значения, например черезcopy().
Можно упомянуть inline-функции: лямбда встраивается в место вызова и объект функции не создаётся, но семантика параметров та же. При передаче массива в vararg через *array создаётся копия массива.
Хорошо связать ответ с Android. Состояние в StateFlow и в Compose сравнивается через equals: если изменить MutableList на месте и отдать ту же ссылку, новое значение равно старому, и не будет ни эмита, ни рекомпозиции. Поэтому состояние держат иммутабельным и заменяют целиком. Данные в Intent между активити, наоборот, проходят через Parcelable и приходят копией.
Где спотыкаются
Говорят «объекты в Kotlin передаются по ссылке». Проверка простая: присвойте параметру новый объект и получите ошибку компиляции, а не изменение снаружи.
Считают List неизменяемым. Это только интерфейс без методов записи, за ним вполне может стоять ArrayList, который меняет кто-то другой.
Мутируют список внутри StateFlow или mutableStateOf и не понимают, почему UI не обновился. Нужно отдавать новый список: list + item или copy().