Inline funkce v Kotlin: co to je, syntaxe a použití

Autor: IT Sectr Publikováno: 2026-06-21 Doba čtení: 9 min

inline funkce — mechanismus Kotlin, při kterém je tělo funkce vloženo přímo do každého místa volání ve fázi kompilace. Tím se eliminuje režie vytváření anonymních tříd a objektů pro parametry lambda. Podle Kotlin Documentation, 2025 je klíčové slovo inline obzvláště účinné pro funkce vyššího řádu, kde každá lambda bez vkládání vytváří samostatný objekt FunctionN, zatěžující garbage collector.

Hlavní body

  • inline funkce — funkce, jejíž tělo je vloženo do místa volání ve fázi kompilace
  • Snižení režie — eliminuje vytváření anonymních tříd a objektů pro lambdy
  • nonlocal return — lambdy uvnitř inline funkcí mohou provést return z vnější funkce
  • noinline — zakazuje vkládání jednotlivých parametrů lambda
  • crossinline — povoluje nonlocal return, ale zakazuje return z kontextu inline funkce

Co je inline funkce v Kotlin?

Inline funkce je funkce označená klíčovým slovem inline. Kompilátor Kotlin pro ni nevytváří samostatný bajtkód s voláním, ale kopíruje tělo funkce přímo do každého místa volání. Hlavním cílem je optimalizace funkcí vyššího řádu, které přijímají výrazy lambda, protože každá lambda v běžné situaci vytváří anonymní objekt třídy Function.

Podle JetBrains Tech Blog (2024) může použití inline funkcí v Kotlin snížit počet vytvořených objektů o 40–60% ve funkcích, které intenzivně používají lambdy. Ve smyčkách a vysoce zatížených operacích (třídění, filtrování kolekcí) to poskytuje měřitelné zvýšení výkonu.

Bez inline je každá lambda zkompilována do anonymní třídy (nebo instance syntetizovaného funkčního rozhraní). Pro lambdy zachycující proměnné jsou vytvářeny další obalové objekty. Inline funkce eliminují všechny tyto objekty ve fázi kompilace a nahrazují je přímým kódem s přístupem k lokálním proměnným bez obalů.

Používejte inline pouze pro funkce s parametry lambda — kompilátor Kotlin sám varuje, pokud inline nepřináší výhodu.

Syntaxe inline funkce a mechanismus práce

Stačí přidat klíčové slovo inline před deklaraci funkce. Kompilátor automaticky vloží tělo funkce do míst volání. Samotná funkce nadále existuje v bajtkódu pro případy, kdy není volána přímo (např. z Java kódu).

kotlin
inline fun Int.repeatAction(action: (Int) -> Unit) {
    for (i in 0 until this) {
        action(i)
    }
}

// Volání — kód lambdy je vložen do těla funkce
5.repeatAction { index ->
    println("Index: $index")
}

Po kompilaci bude výše uvedený kód ekvivalentní:

kotlin
// Co se stane po vložení (schematicky):
val $this = 5
for (i in 0 until $this) {
    println("Index: $i")
}

Nevytváří se žádný objekt pro lambdu — kód action se provádí přímo. Toto je podstata optimalizace: místo volání Function.invoke() — přímé vložení kódu s tělem lambdy.

Kontrola pomocí dekompilace

Pro kontrolu vkládání otevřete Tools > Kotlin > Show Kotlin Bytecode v IntelliJ IDEA a klikněte na Decompile. Uvidíte, že místo volání repeatAction s lambdou se generuje přímé vložení těla funkce se smyčkou for.

Problém režie lambd a jeho řešení

Každá lambda v Kotlin je zkompilována do jedné ze tří variant. První — pokud lambda nezachycuje proměnné, stává se statickou metodou třídy, ve které je deklarována. Druhá — pokud zachycuje jednu proměnnou, je vytvořena anonymní třída. Třetí — pokud zachycuje více proměnných, je vytvořena anonymní třída s poli pro každou zachycenou proměnnou.

Typ lambdyBez inlineS inline
Bez zachyceníJedna statická metoda (znovu použitelná)Plné vložení, bez volání
Se zachycením 1 proměnnéAnonymní třída (jeden objekt)Plné vložení, bez objektu
Se zachycením N proměnnýchAnonymní třída s N poliPlné vložení, bez objektu
RekurzivníBěžné voláníinline zakázáno

Podle Android Performance Patterns (Google, 2024) v aplikacích s intenzivním používáním kolekcí (filtrování, třídění, seskupování) inline funkce snižují počet alokací o 25–35%. Efekt je zvláště patrný v Jetpack Compose, kde každá změna stavu způsobuje překompozici s mnoha lambdami.

Nonlocal return a omezení

Lambda v běžné funkci nemůže provést return z vnější funkce — pouze lokální return ze samotné lambdy (přes return@label). V inline funkci je lambda vložena do těla volající funkce, proto nonlocal return je možný: return uvnitř lambdy ukončuje vnější funkci.

kotlin
inline fun findFirst(
    items: List<Int>,
    predicate: (Int) -> Boolean
): Int {
    for (item in items) {
        if (predicate(item)) {
            return item
        }
    }
    return -1
}

fun processNumbers() {
    val numbers = listOf(1, 2, 3)
    val firstEven = findFirst(numbers) { it % 2 == 0 }
    // return v lambdě by vrátil null z processNumbers()
}

Nonlocal return je vhodný pro předčasné ukončení, ale může vést k chybám. Pokud je lambda použita v nelokálním kontextu (uložena do proměnné), nonlocal return způsobí RuntimeException. Kompilátor Kotlin vydává varování při pokusu o takové uložení.

noinline a crossinline: správa vkládání

Když má funkce několik parametrů lambda, někdy je třeba vložit pouze část z nich. K tomu slouží noinline — zakazuje vkládání konkrétního parametru lambda a ponechává jej jako běžný objekt Function.

Modifikátor crossinline řeší opačný problém: lambda je vložena, ale nonlocal return je zakázán. To je potřeba, když je lambda použita uvnitř jiné lambdy nebo v kontextu, kde return není povolen (např. předána do Runnable).

kotlin
inline fun processWithCallback(
    data: String,
    crossinline onSuccess: (String) -> Unit,
    noinline onError: (Exception) -> Unit
) {
    try {
        val result = process(data)
        onSuccess(result)
    } catch (e: Exception) {
        onError(e)
    }
}

// noinline: onError může být uložen v proměnné nebo předán jinam
val errorHandler = { e: Exception -> log(e.message) }
processWithCallback("input", { println(it) }, errorHandler)

V příkladu je onSuccess označena jako crossinline — bude vložena, ale uvnitř ní nelze použít return. onError je označena jako noinline — není vložena, lze ji předat jako objekt, uložit do pole třídy nebo použít jako listener.

Omezení inline funkcí a doporučení

Inline funkce mají omezení. Rekurzivní inline funkce jsou zakázány — kompilátor zobrazí chybu. Inline funkce nemohou mít viditelnost private nebo internal, pokud jsou deklarovány v jiném modulu, ale toto omezení souvisí s přístupem, nikoli se samotným mechanismem vkládání.

Velikost bajtkódu roste s každým voláním inline funkce, protože tělo je kopírováno. Podle Kotlin Coding Conventions (JetBrains, 2025) se doporučuje používat inline pouze pro funkce o velikosti do 10–15 řádků. U velkých funkcí může být výhoda z vkládání lambd anulována zvýšením velikosti APK (v Android je to kritické — existuje limit 64K metod).

kotlin
// Doporučená praxe
inline fun withLock(lock: Lock, action: () -> T): T {
    lock.lock()
    try {
        return action()
    } finally {
        lock.unlock()
    }
}

// Nedoporučuje se pro velké funkce
inline fun largeComputation(...) { // špatně — tělo >50 řádků
    // více než 50 řádků — raději extrahovat do běžné funkce
}

Veřejné inline funkce v knihovnách vyžadují opatrnost: pokud se tělo inline funkce změní, všichni klienti musí překompilovat. JetBrains doporučuje používat @PublishedApi internal pro členy volané z inline funkcí, aby byla zachována kompatibilita v rámci modulu.

Často kladené otázky

Lze vytvořit inline extension funkci?

Ano, inline extension funkce funguje bez omezení. Například: inline fun String.transform(block: (Char) -> Char): String. Rozšíření neovlivňuje možnost vkládání — kompilátor ji zpracovává stejně jako běžnou inline funkci.

Kdy inline NEPřináší výhodu?

Pokud funkce nepřijímá parametry lambda — inline neposkytuje výhodu. Kompilátor Kotlin vydává varování: "Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types." Také inline je škodlivý pro velké funkce kvůli růstu bajtkódu.

Čím se inline liší od @JvmInline (value class)?

inline — modifikátor funkce, který vkládá její tělo do místa volání. @JvmInline (value class) — mechanismus pro obalové třídy, které jsou během kompilace nahrazeny hodnotou. Různé koncepty: inline optimalizuje volání, value class optimalizuje reprezentaci dat.

Lze použít inline se suspend funkcemi?

Ne, suspend funkce nemohou být inline, protože jsou kompilovány do stavového stroje s Continuation. Nicméně inline funkce může přijmout suspend lambdu jako parametr s crossinline. To je často používáno v korutinách: inline fun launch(block: suspend CoroutineScope.() -> Unit).

Ovlivňuje inline ladění?

Ano, inline funkce ztěžují ladění, protože tělo funkce není voláno, ale vkládáno do místa volání. Stacktrace se prodlužuje, body přerušení fungují, ale mohou zobrazovat neočekávané pozice. JetBrains doporučuje ladit bez inline a zapínat jej pouze v release sestaveních.

Shrnutí

  • inline funkce — vkládá tělo funkce do místa volání, eliminuje režii lambd
  • Nonlocal return — return z lambdy ukončuje vnější funkci (možné pouze v inline)
  • noinline — zakazuje vkládání konkrétního parametru lambda
  • crossinline — povoluje vkládání, ale zakazuje nonlocal return
  • Rekurzivní funkce nemohou být inline — kompilátor zobrazí chybu
  • Velikost bajtkódu roste — používejte inline pro funkce do 10–15 řádků
  • Optimální použití — funkce vyššího řádu s parametry lambda, synchronizační bloky, scope funkce (let, apply, also, run)

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také