> Что такое crossinline в Kotlin и зачем он нужен (Kotlin, Android)

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

Компании: TrendTech

Стек: Kotlin, Android

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

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

crossinline - это модификатор в Kotlin для параметров-функций inline-функций. Он запрещает внутри такой функции использовать return для выхода из внешней функции, но при этом позволяет вызывать её в другом контексте выполнения (например, внутри лямбды или локального объекта). Без crossinline компилятор не даст вызвать параметр-функцию из вложенной лямбды, потому что это нарушит контроль нелокального return. По сути, crossinline - это компромисс между производительностью inline и безопасностью управления потоком выполнения.

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

В Kotlin inline-функции подставляют свой код прямо в место вызова, что убирает накладные расходы на создание лямбды. При этом параметры-функции по умолчанию поддерживают нелокальный return - то есть внутри лямбды можно выйти из всей внешней функции.

Проблема возникает, когда inline-функция передаёт свою лямбду-параметр в другой контекст выполнения - например, в другую лямбду, которая не является inline, или в объект. В этом случае нелокальный return становится небезопасным: компилятор не может гарантировать, что лямбда выполнится синхронно в том же стеке вызовов.

crossinline решает эту проблему: он запрещает нелокальный return внутри переданной лямбды, но сохраняет возможность вызывать её из вложенных лямбд. Это позволяет использовать inline-функции в сценариях, где лямбда передаётся дальше, например, в forEach, run, with или в собственные утилиты.

Важно: crossinline применяется только к параметрам-функциям inline-функций. Для обычных (не inline) функций он не имеет смысла.

На практике

В Android-разработке crossinline часто встречается при написании собственных inline-функций, которые оборачивают вызовы с контекстом или жизненным циклом. Например, функция, которая выполняет действие только если LifecycleOwner активен, или обёртка для runOnUiThread.

Также crossinline используется в стандартной библиотеке Kotlin - например, в runCatching, use, synchronized. Это позволяет сохранить производительность inline, но при этом безопасно передавать лямбду во внутренние механизмы.

На собеседовании от junior-кандидата обычно ожидают понимание базовой идеи: crossinline нужен, чтобы разрешить вызов лямбды из вложенного контекста, пожертвовав нелокальным return.

Пример кода

inline fun measureTime(crossinline block: () -> Unit) {
    val start = System.currentTimeMillis()
    // Без crossinline здесь была бы ошибка компиляции
    Runnable {
        block() // вызов из другого контекста
    }.run()
    println("Time: ${System.currentTimeMillis() - start}")
}

fun main() {
    measureTime {
        // Нельзя написать return - компилятор запретит
        println("Doing work")
    }
}

Если убрать crossinline, компилятор выдаст ошибку: "Illegal usage of inline-parameter". При этом внутри лямбды в main нельзя использовать return - это ключевое отличие от обычного inline-параметра.

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

Начни с определения: crossinline - модификатор для параметров inline-функций, который запрещает нелокальный return, но разрешает вызов лямбды из вложенных лямбд. Затем объясни проблему: без него нельзя передать лямбду в другой контекст выполнения. Приведи пример из стандартной библиотеки или Android. Если спросят про производительность - скажи, что crossinline не влияет на производительность, он только меняет правила для return. Не углубляйся в детали компилятора, если не просят.

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

Интервьюер проверяет:

  • понимание inline-механизма и нелокального return
  • знание ограничений inline-функций
  • умение объяснить разницу между noinline и crossinline
  • способность привести практический пример

Для junior-уровня достаточно уверенного объяснения базовой концепции и одного примера. Если кандидат путает crossinline с noinline - это красный флаг.

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

  • Путаница с noinline: noinline запрещает инлайнинг параметра вообще, а crossinline разрешает инлайнинг, но запрещает нелокальный return.
  • Утверждение, что crossinline нужен для производительности - это не так, он нужен для корректности компиляции.
  • Попытка использовать crossinline в обычных (не inline) функциях - это синтаксическая ошибка.
  • Непонимание, что crossinline не запрещает сам return внутри лямбды, а запрещает только выход из внешней функции.

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

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