Ключевое слово inline
Ключевое слово inline используется для пометки функций,
которые должны быть встроены (inlined) на месте их вызова.
Это означает, что вместо обычного вызова функции
компилятор подставит тело функции непосредственно в место вызова.
Это особенно полезно для функций, принимающих лямбда-выражения
в качестве параметров, так как позволяет избежать создания
дополнительных объектов и улучшить производительность.
Синтаксис
inline fun <имя_функции>(<параметры>): <возвращаемый_тип> {
// тело функции
}
inline fun <T> <имя_функции>(<параметры>): <возвращаемый_тип> {
// тело функции с обобщенным типом
}
inline fun <имя_функции>(crossinline <параметр>: () -> Unit): <возвращаемый_тип> {
// тело функции с crossinline параметром
}
inline fun <имя_функции>(noinline <параметр>: () -> Unit): <возвращаемый_тип> {
// тело функции с noinline параметром
}
Пример
Создадим простую inline-функцию, которая выполняет переданное лямбда-выражение и измеряет время выполнения:
inline fun measureTime(block: () -> Unit) {
val start = System.currentTimeMillis()
block()
val end = System.currentTimeMillis()
println("Execution time: ${end - start} ms")
}
// Использование функции
measureTime {
var sum = 0
for (i in 1..1000) {
sum += i
}
println("Sum: $sum")
}
После компиляции код будет преобразован примерно так:
val start = System.currentTimeMillis()
var sum = 0
for (i in 1..1000) {
sum += i
}
println("Sum: $sum")
val end = System.currentTimeMillis()
println("Execution time: ${end - start} ms")
Пример
Использование noinline для указания, что конкретный
лямбда-параметр не должен быть встроен:
inline fun processData(
data: List<Int>,
noinline validator: (Int) -> Boolean,
transformer: (Int) -> Int
): List<Int> {
return data.filter(validator).map(transformer)
}
val numbers = listOf(1, 2, 3, 4, 5)
val isEven = { n: Int -> n % 2 == 0 }
val squared = { n: Int -> n * n }
val res = processData(numbers, isEven, squared)
println(res)
Результат выполнения кода:
List<Int> [4, 16]
Пример
Использование crossinline для лямбд, которые
должны быть выполнены в другом контексте:
inline fun runAsync(crossinline block: () -> Unit) {
Thread {
block()
}.start()
}
runAsync {
println("Running in background thread")
}
Результат выполнения кода:
"Running in background thread"
Пример
Inline-функции с обобщенными типами:
inline fun <T> T.applyIf(condition: Boolean, block: T.() -> T): T {
return if (condition) block() else this
}
val number = 5
val res = number.applyIf(number > 0) {
this * 2
}
println(res)
Результат выполнения кода:
Int 10
Когда использовать inline
Используйте inline для:
- Функций высшего порядка (принимающих лямбды)
- Небольших функций, где встраивание улучшит производительность
- Функций, которые работают с обобщенными типами в runtime
Не используйте inline для:
- Больших функций (увеличивает размер bytecode)
- Рекурсивных функций
- Функций, которые вызываются редко
Смотрите также
-
функции высшего порядка
fun,
которые принимают другие функции в качестве параметров