> Как передаются параметры функции в Kotlin, по ссылке или по значению (Kotlin, Android)

Уровень: senior · Роль: mobile · Категория: Технические вопросы

Компании: Юрент

Стек: Kotlin, Android

> Пример ответа

Короткий ответ

В Kotlin параметры функций всегда передаются по значению. Для примитивных типов (Int, Boolean и т.д.) копируется само значение. Для ссылочных типов копируется ссылка на объект, но не сам объект. Это означает, что внутри функции вы можете изменить состояние объекта, на который указывает ссылка, но не можете переназначить саму ссылку так, чтобы это повлияло на вызывающий код.

Подробное объяснение

Kotlin, как и Java, использует строго семантику pass-by-value. Разберём это на двух уровнях:

  1. Примитивные типы: Int, Long, Double, Boolean, Char и т.д. - при передаче в функцию создаётся копия значения. Любые изменения параметра внутри функции не влияют на исходную переменную.

  2. Ссылочные типы: классы, data class, коллекции, строки (String - особый случай, но тоже ссылочный тип). При передаче копируется значение ссылки (адрес объекта в памяти). Исходная переменная и параметр функции указывают на один и тот же объект. Поэтому:

    • Изменение полей объекта внутри функции видно снаружи.
    • Присваивание нового значения параметру внутри функции не влияет на исходную переменную.

Важно понимать, что в Kotlin нет понятия "out" или "ref" параметров, как в C#. Вместо этого используются:

  • Возврат нового значения.
  • Классы-обёртки (например, AtomicReference).
  • Data class с копированием.

На практике

На Android-разработке это особенно важно при работе с:

  • LiveData и StateFlow: передавая их в функции, вы работаете с тем же экземпляром, поэтому изменение значения через value или emit видно всем наблюдателям.
  • Адаптерами RecyclerView: передавая список в адаптер, вы передаёте ссылку. Если внутри адаптера изменить список (например, через clear() и addAll()), это повлияет на оригинальный список. Но если присвоить параметру новый список - оригинал не изменится.
  • Compose: при передаче state-объектов важно помнить, что изменение полей объекта не вызовет рекомпозицию, если объект не является immutable или не используется mutableStateOf.

Пример кода

data class User(var name: String, var age: Int)

fun modifyUser(user: User) {
    user.name = "Новое имя" // Изменение видно снаружи
    user = User("Другой", 30) // Ошибка компиляции: val параметр
}

fun modifyUserWithNew(user: User) {
    user.age = 99 // Изменение видно снаружи
    // Присваивание новой ссылки невозможно, параметр - val
}

fun main() {
    val user = User("Иван", 25)
    modifyUser(user)
    println(user.name) // "Новое имя"
    
    var number = 10
    fun increment(n: Int) {
        // n = n + 1 - ошибка, параметр val
    }
    // Для изменения числа нужно возвращать значение
}

Как отвечать на собеседовании

Начните с чёткого утверждения: "В Kotlin всё передаётся по значению". Затем поясните разницу между примитивами и ссылочными типами. Приведите пример с изменением объекта и попыткой переназначить ссылку. Упомяните, что это поведение унаследовано от JVM и отличается от языков с pass-by-reference (C++, C# с ref). Если спросят про производительность - отметьте, что копирование ссылки (8 байт) дешевле копирования объекта.

Что проверяет интервьюер

  • Понимание фундаментальных основ JVM и Kotlin.
  • Умение объяснить разницу между изменением объекта и переназначением ссылки.
  • Знание практических последствий для Android-разработки (мутабельность, состояние UI).
  • Понимание, почему в Kotlin нет ref/out параметров и какие альтернативы используются.

Типичные ошибки

  • Утверждение, что объекты передаются по ссылке - это неверно, передаётся копия ссылки.
  • Путаница между изменением состояния объекта и изменением ссылки.
  • Забывают, что параметры в Kotlin всегда val, поэтому попытка присвоить новое значение параметру - ошибка компиляции.
  • Непонимание, что String - неизменяемый объект, поэтому любые операции со строками создают новый объект, а исходная строка не меняется.
  • Приводят пример с Java и говорят, что "в Java всё по ссылке" - это тоже неверно, Java использует ту же семантику.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью