Inline function sa Kotlin: ano ito, syntax at aplikasyon

May-akda: IT Sectr Nai-publish: 2026-06-21 Oras ng pagbabasa: 9 min

inline function — mekanismo ng Kotlin kung saan ang katawan ng function ay direktang inilalagay sa bawat lugar ng tawag sa yugto ng kompilasyon. Tinatanggal nito ang overhead mula sa paglikha ng mga anonymous na klase at object para sa mga lambda parameter. Ayon sa Kotlin Documentation, 2025, ang keyword na inline ay lalong epektibo para sa higher-order function, kung saan bawat lambda nang walang pag-embed ay lumilikha ng hiwalay na FunctionN object, na nagpapabigat sa garbage collector.

Mga Pangunahing Punto

  • inline function — function na ang katawan ay inilalagay sa lugar ng tawag sa yugto ng kompilasyon
  • Pagbawas ng overhead — tinatanggal ang paglikha ng mga anonymous na klase at object para sa lambda
  • nonlocal return — mga lambda sa loob ng inline function ay maaaring magsagawa ng return mula sa panlabas na function
  • noinline — nagbabawal sa pag-embed ng mga indibidwal na lambda parameter
  • crossinline — nagpapahintulot ng nonlocal return, ngunit nagbabawal ng return mula sa konteksto ng inline function

Ano ang inline function sa Kotlin?

Ang inline function ay isang function na minarkahan ng keyword na inline. Ang Kotlin compiler ay hindi lumilikha ng hiwalay na bytecode na may tawag para dito, kundi kinokopya ang katawan ng function nang direkta sa bawat lugar ng tawag. Ang pangunahing layunin — optimisasyon ng higher-order function na tumatanggap ng lambda expression, dahil ang bawat lambda sa normal na sitwasyon ay lumilikha ng anonymous object ng Function class.

Ayon sa JetBrains Tech Blog (2024), ang paggamit ng inline function sa Kotlin ay maaaring mabawasan ang bilang ng mga nilikha na object ng 40–60% sa mga function na intensibong gumagamit ng lambda. Sa mga loop at mataas na kargang operasyon (pag-uuri, pag-filter ng mga koleksyon) ito ay nagbibigay ng nasusukat na pagtaas ng pagganap.

Kung walang inline, ang bawat lambda ay nako-compile sa isang anonymous na klase (o instance ng isang synthesize na functional interface). Para sa mga lambda na kumukuha ng variable, nililikha ang mga karagdagang wrapper object. Tinatanggal ng inline function ang lahat ng mga object na ito sa yugto ng kompilasyon, pinapalitan ang mga ito ng direktang code na may access sa lokal na variable na walang wrapper.

Gamitin ang inline lamang para sa mga function na may lambda parameter — ang Kotlin compiler mismo ay nagbababala kung ang inline ay hindi nagbibigay ng pakinabang.

Syntax ng inline function at mekanismo ng trabaho

Sapat na idagdag ang keyword na inline bago ang deklarasyon ng function. Awtomatikong inilalagay ng compiler ang katawan ng function sa mga lugar ng tawag. Ang function mismo ay patuloy na umiiral sa bytecode para sa mga pagkakataon kung saan hindi ito direktang tinatawag (halimbawa, mula sa Java code).

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

// Tawag — lambda code ay naka-embed sa katawan ng function
5.repeatAction { index ->
    println("Index: $index")
}

Pagkatapos ng kompilasyon, ang code sa itaas ay magiging katumbas ng:

kotlin
// Ano ang mangyayari pagkatapos ng pag-embed (eskematiko):
val $this = 5
for (i in 0 until $this) {
    println("Index: $i")
}

Walang object na nilikha para sa lambda — ang action code ay direktang naisasagawa. Ito ang esensya ng optimisasyon: sa halip na tawag ng Function.invoke() — direktang pag-embed ng code na may katawan ng lambda.

Pagsusuri sa pamamagitan ng decompilation

Upang suriin ang pag-embed, buksan ang Tools > Kotlin > Show Kotlin Bytecode sa IntelliJ IDEA at pindutin ang Decompile. Makikita mo na sa halip na tawag ng repeatAction na may lambda, direktang pag-embed ng katawan ng function na may for loop ang nabubuo.

Problema ng overhead ng lambda at solusyon nito

Ang bawat lambda sa Kotlin ay nako-compile sa isa sa tatlong variant. Una — kung ang lambda ay hindi kumukuha ng variable, ito ay nagiging static method ng klase kung saan ito na-deklara. Ikalawa — kung kumukuha ng isang variable, nililikha ang anonymous na klase. Ikatlo — kung kumukuha ng maraming variable, nililikha ang anonymous na klase na may mga field para sa bawat nakuhang variable.

Uri ng LambdaWalang inlineMay inline
Walang pagkuhaIsang static method (ginagamit muli)Buong pag-embed, walang tawag
May pagkuha ng 1 variableAnonymous na klase (isang object)Buong pag-embed, walang object
May pagkuha ng N variableAnonymous na klase na may N fieldBuong pag-embed, walang object
RekursiboKaraniwang tawaginline bawal

Ayon sa Android Performance Patterns (Google, 2024), sa mga application na may intensibong paggamit ng koleksyon (pag-filter, pag-uuri, pagpapangkat) ang inline function ay nagbabawas ng bilang ng mga alokasyon ng 25–35%. Ang epekto ay lalong kapansin-pansin sa Jetpack Compose, kung saan ang bawat pagbabago ng estado ay nagdudulot ng muling komposisyon na may maraming lambda.

Nonlocal return at mga limitasyon

Ang lambda sa isang ordinaryong function ay hindi maaaring magsagawa ng return mula sa panlabas na function — tanging lokal na return mula sa lambda mismo (sa pamamagitan ng return@label). Sa inline function, ang lambda ay inilalagay sa katawan ng tumatawag na function, kaya nonlocal return ay nagiging posible: ang return sa loob ng lambda ay nagtatapos sa panlabas na function.

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 sa lambda ay magbabalik ng null mula sa processNumbers()
}

Nonlocal return ay maginhawa para sa maagang pagtatapos, ngunit maaaring humantong sa mga error. Kung ang lambda ay ginamit sa nonlocal na konteksto (ini-save sa variable), ang nonlocal return ay magdudulot ng RuntimeException. Ang Kotlin compiler ay naglalabas ng babala sa pagtatangkang mag-save ng ganito.

noinline at crossinline: pamamahala ng pag-embed

Kapag ang isang function ay may maraming lambda parameter, minsan kailangan lamang i-embed ang bahagi ng mga ito. Para dito ginagamit ang noinline — nagbabawal sa pag-embed ng isang partikular na lambda parameter, iniiwan ito bilang isang ordinaryong Function object.

Ang modifikator na crossinline ay lumulutas sa kabaligtaran na problema: ang lambda ay naka-embed, ngunit ang nonlocal return ay bawal. Ito ay kailangan kapag ang lambda ay ginamit sa loob ng isa pang lambda o sa konteksto kung saan ang return ay hindi pinapayagan (halimbawa, ipinasa sa 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: ang onError ay maaaring i-save sa variable o ipasa sa ibang lugar
val errorHandler = { e: Exception -> log(e.message) }
processWithCallback("input", { println(it) }, errorHandler)

Sa halimbawa, ang onSuccess ay minarkahan bilang crossinline — i-e-embed, ngunit sa loob nito ay hindi maaaring gumamit ng return. Ang onError ay minarkahan bilang noinline — hindi naka-embed, maaaring ipasa bilang object, i-save sa field ng klase, o gamitin bilang listener.

Mga limitasyon ng inline function at rekomendasyon

Ang inline function ay may mga limitasyon. Ang mga rekursibong inline function ay bawal — ang compiler ay maglalabas ng error. Ang inline function ay hindi maaaring magkaroon ng private o internal visibility kung sila ay na-deklara sa ibang module, ngunit ang limitasyong ito ay may kinalaman sa access, hindi sa mekanismo ng pag-embed mismo.

Ang laki ng bytecode ay lumalaki sa bawat tawag ng inline function, dahil ang katawan ay kinokopya. Ayon sa Kotlin Coding Conventions (JetBrains, 2025), inirerekomenda na gamitin ang inline lamang para sa mga function na may sukat na hanggang 10–15 linya. Para sa malalaking function, ang pakinabang mula sa pag-embed ng lambda ay maaaring mawala dahil sa pagtaas ng laki ng APK (sa Android ito ay kritikal — may limit na 64K method).

kotlin
// Inirerekomendang praktika
inline fun withLock(lock: Lock, action: () -> T): T {
    lock.lock()
    try {
        return action()
    } finally {
        lock.unlock()
    }
}

// Hindi inirerekomenda para sa malalaking function
inline fun largeComputation(...) { // masama — katawan >50 linya
    // higit sa 50 linya — mas mahusay na i-extract sa ordinaryong function
}

Ang pampublikong inline function sa mga library ay nangangailangan ng pag-iingat: kung ang katawan ng inline function ay magbabago, lahat ng client ay dapat mag-recompile. Inirerekomenda ng JetBrains ang paggamit ng @PublishedApi internal para sa mga miyembro na tinatawag mula sa inline function, upang mapanatili ang compatibility sa loob ng module.

Mga Madalas Itanong

Maaari bang gumawa ng inline extension function?

Oo, ang inline extension function ay gumagana nang walang limitasyon. Halimbawa: inline fun String.transform(block: (Char) -> Char): String. Ang extension ay hindi nakakaapekto sa kakayahang mag-embed — pinoproseso ito ng compiler tulad ng ordinaryong inline function.

Kailan HINDI nagbibigay ng pakinabang ang inline?

Kung ang function ay hindi tumatanggap ng lambda parameter — ang inline ay hindi nagbibigay ng kalamangan. Ang Kotlin compiler ay naglalabas ng babala: "Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types." Gayundin, ang inline ay nakakapinsala para sa malalaking function dahil sa paglaki ng bytecode.

Paano naiiba ang inline sa @JvmInline (value class)?

inline — modifikator ng function na nag-e-embed ng katawan nito sa lugar ng tawag. @JvmInline (value class) — mekanismo para sa wrapper class na pinapalitan ng halaga sa panahon ng kompilasyon. Magkaibang konsepto: inline ay nag-o-optimize ng mga tawag, value class ay nag-o-optimize ng representasyon ng datos.

Maaari bang gamitin ang inline sa suspend function?

Hindi, ang suspend function ay hindi maaaring inline, dahil sila ay nako-compile sa state machine na may Continuation. Gayunpaman, ang inline function ay maaaring tumanggap ng suspend lambda bilang parameter na may crossinline. Ito ay madalas na ginagamit sa coroutine: inline fun launch(block: suspend CoroutineScope.() -> Unit).

Nakakaapekto ba ang inline sa pag-debug?

Oo, ang inline function ay nagpapahirap sa pag-debug, dahil ang katawan ng function ay hindi tinatawag, kundi naka-embed sa lugar ng tawag. Ang stacktrace ay nagiging mas mahaba, gumagana ang mga breakpoint ngunit maaaring magpakita ng hindi inaasahang posisyon. Inirerekomenda ng JetBrains ang pag-debug nang walang inline, at i-activate lamang ito sa release build.

Buod

  • inline function — nag-e-embed ng katawan ng function sa lugar ng tawag, tinatanggal ang overhead ng lambda
  • Nonlocal return — return mula sa lambda nagtatapos sa panlabas na function (posible lamang sa inline)
  • noinline — nagbabawal sa pag-embed ng partikular na lambda parameter
  • crossinline — nagpapahintulot ng pag-embed ngunit nagbabawal ng nonlocal return
  • Rekursibong function ay hindi maaaring inline — ang compiler ay naglalabas ng error
  • Laki ng bytecode ay lumalaki — gamitin ang inline para sa function hanggang 10–15 linya
  • Optimal na aplikasyon — higher-order function na may lambda parameter, synchronization block, scope functions (let, apply, also, run)

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din