inline-функции: устранение накладных расходов лямбд
Помечайте функции как inline, чтобы не создавать объекты для параметров-лямбд.
«inline-функции: устранение накладных расходов лямбд» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Что такое встроенная функция
Обычно лямбда, переданная функции, компилируется в анонимный класс. При каждом вызове выделяется новый объект, что требует памяти и времени. Ключевое слово inline указывает компилятору скопировать тело функции вместе с её аргументами-лямбдами непосредственно в место вызова.
Объявление встроенной функции
Добавьте модификатор inline перед fun:
inline fun measureTime(block: () -> Unit): Long {
val start = System.nanoTime()
block()
return System.nanoTime() - start
}Как компилятор переписывает вызов
Вызов вроде measureTime { doWork() } на уровне байткода превращается во встроенное тело measureTime, вставленное непосредственно в место вызова: объект лямбды вообще не выделяется.
Когда использовать встраивание
Используйте inline, когда:
- Функция принимает один или несколько параметров-лямбд
- Она часто вызывается на критических по производительности участках (в тесных циклах, в composable-функциях)
- Вам нужны параметры типов
reified(они рассматриваются далее)
Пример сравнения производительности
Без inline каждый вызов функции высшего порядка выделяет объект лямбды. С ним JVM видит последовательный код — без выделения памяти и виртуальной диспетчеризации.
inline fun repeat(n: Int, block: () -> Unit) {
for (i in 0 until n) block()
}Нелокальные возвраты
Важное преимущество встроенных функций: лямбда может использовать return, чтобы выйти из охватывающей функции, а не только из самой лямбды. Это называется нелокальным возвратом.
inline fun forEach(list: List<Int>, block: (Int) -> Unit) {
for (item in list) block(item)
}
fun findFirst(list: List<Int>): Int {
forEach(list) { if (it > 5) return it } // returns from findFirst
return -1
}Ограничения встраивания
Встроенные функции нельзя сохранять в переменных или передавать как объекты, поскольку во время выполнения они не существуют как самостоятельные сущности. Нельзя вызвать f(::measureTime), если f ожидает ссылку на функцию с такой сигнатурой.
Встраивание конвейеров коллекций
Функции стандартной библиотеки map, filter, forEach и другие являются inline. Поэтому их объединение в цепочку не создаёт дополнительных объектов замыканий для каждого элемента.
val result = (1..1_000_000)
.filter { it % 2 == 0 } // inline
.map { it * it } // inline
.take(10)Компромисс между размером кода и производительностью
Каждое место вызова получает копию встроенного кода. Если тело функции большое и вызывается из многих мест, размер байткода увеличивается. Предпочитайте inline для небольших, часто вызываемых лямбд.
Взаимодействие с функциями companion и верхнего уровня
inline работает с функциями верхнего уровня и функциями-членами. Он не работает со свойствами или конструкторами. Функция должна быть видима в месте вызова (обычно иметь модификатор public или internal).
Примеры из стандартной библиотеки
Уже знакомые вам функции, являющиеся inline: let, run, apply, also, with, use, synchronized, lazy (вариант с блоком). Именно модификатор inline делает их лямбды не требующими дополнительных затрат.
Быстрая проверка
Каково главное преимущество пометки функции высшего порядка как inline?
Повторение: встроенные функции
Главные выводы:
inlineустраняет выделение объектов лямбд- Позволяет выполнять нелокальные возвраты из лямбд
- Требуется для параметров типов
reified - Лучше всего подходит для небольших, часто вызываемых функций высшего порядка
- Все функции областей действия стандартной библиотеки являются
inline
Часто задаваемые вопросы
Урок «inline-функции: устранение накладных расходов лямбд» бесплатный?
Да — полный текст урока «inline-функции: устранение накладных расходов лямбд» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «inline-функции: устранение накладных расходов лямбд»?
Помечайте функции как inline, чтобы не создавать объекты для параметров-лямбд. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «inline-функции: устранение накладных расходов лямбд»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- inline-функции: устранение накладных расходов лямбд
- Модификаторы noinline и crossinline
- Параметры типов reified: доступ к T во время выполнения
- Практические шаблоны reified: разбор, DI и сериализация