Inline function adalah function yang ditandai dengan keyword inline. Kompilator Kotlin akan menyisipkan body function langsung ke setiap pemanggil, menghilangkan overhead pembuatan objek lambda dan pemanggilan function. Pada chapter ini kita akan memahami cara kerja inline function, modifikator noinline dan crossinline untuk kasus khusus, dan bagaimana inline memungkinkan fitur reified type parameter yang tidak mungkin dilakukan function biasa. Kita juga akan melihat kapan inline memberi manfaat nyata dan kapan tidak.
Apa Itu Inline Function #
Function inline ditandai dengan keyword inline sebelum fun. Saat kompilasi, setiap pemanggilan function akan diganti dengan body function itu sendiri — termasuk lambda yang diteruskan. Hal ini mengurangi overhead alokasi lambda dan call stack.
inline fun repotimes(n: Int, aksi: (Int) -> Unit) {
for (i in 0 until n) aksi(i)
}
// Setiap pemanggilan repotimes(...) akan disalin penuh ke pemanggil
repotimes(3) { println(it) }Contoh Inline Function #
Mari kita lihat inline function dalam berbagai variasi — inline, noinline, crossinline, dan kombinasi dengan reified.
// inline_functions.kt
// Inline function: kompilator menyisipkan body ke setiap pemanggil.
// Higher-order function inline untuk menghindari alokasi lambda.
inline fun repotimes(n: Int, aksi: (Int) -> Unit) {
for (i in 0 until n) aksi(i)
}
// noinline: parameter function tetap tidak di-inline.
inline fun prosesGabungan(
nilai: Int,
noinline a: (Int) -> Int,
noinline b: (Int) -> Int
): Int {
return a(b(nilai))
}
// crossinline: tidak boleh return non-local, biasanya untuk lambda
// yang dipanggil dari eksekusi lain.
inline fun jadwalTugas(crossinline tugas: () -> Unit) {
val runner = Runnable { tugas() }
runner.run()
}
// reified type parameter (memerlukan inline).
inline fun <reified T> namaTipe(): String = T::class.simpleName ?: "<anonim>"
fun main() {
// Pemanggilan inline function — lambda digabung ke pemanggil.
repotimes(3) { i -> println(" iterasi $i") }
// noinline + inline.
val hasil = prosesGabungan(
nilai = 5,
a = { it + 10 },
b = { it * 2 }
)
println("prosesGabungan(5) = $hasil")
// crossinline.
jadwalTugas { println(" tugas dijadwalkan") }
// reified.
println("Tipe Int: ${namaTipe<Int>()}")
println("Tipe String: ${namaTipe<String>()}")
}Output yang Dihasilkan:
iterasi 0
iterasi 1
iterasi 2
prosesGabungan(5) = 20
tugas dijadwalkan
Tipe Int: Int
Tipe String: StringMari kita telaah baris-baris kode di atas:
- Baris 5 (
inline fun repotimes(n: Int, aksi: (Int) -> Unit)): functioninline. Parameteraksibertipe function type. Saat dipanggil, bodyrepotimesdan lambda yang diteruskan akan digabungkan ke pemanggil — tidak ada objek lambda yang dibuat. - Baris 11-12 (
noinline a: (Int) -> Int, noinline b: (Int) -> Int): modifikatornoinlinememaksa parameteradanbtetap tidak di-inline. Berguna saat kita ingin menyimpan lambda atau meneruskannya ke function lain. - Baris 20 (
inline fun jadwalTugas(crossinline tugas: () -> Unit)): modifikatorcrossinlinemelarang non-local return. Dipakai bila lambda akan dipanggil dari konteks lain (di sini dari dalamRunnable), di mana non-local return tidak masuk akal. - Baris 28 (
inline fun <reified T> namaTipe(): String = T::class.simpleName ?: "<anonim>"): functioninlinedenganreified T. Reified memungkinkan aksesT::classsaat runtime — sesuatu yang tidak bisa dilakukan function biasa karena type erasure. - Baris 33 (
repotimes(3) { i -> println(" iterasi $i") }): pemanggilan function inline. Lambda{ i -> ... }akan digabung ke bodyrepotimesdi lokasi pemanggilan. - Baris 37-41 (
prosesGabungan(nilai = 5, a = { it + 10 }, b = { it * 2 })): pemanggilan dengan dua lambdanoinline. FunctionprosesGabunganakan di-inline, tetapi lambdaadanbtetap dibuat sebagai objek karenanoinline. - Baris 45 (
jadwalTugas { println(" tugas dijadwalkan") }): lambda crossinline dipanggil dari dalamRunnable. Bila lambda mencobareturn, kompilator menolak karenacrossinlinemelarang non-local return. - Baris 48-49 (
namaTipe<Int>()dannamaTipe<String>()): pemanggilan function reified. Kompilator menggantiTdengan tipe konkret (IntatauString) di setiap pemanggilan, sehinggaT::class.simpleNamemenghasilkan"Int"atau"String".
Modifikator pada Parameter Function Type #
| Modifikator | Perilaku | Kapan Dipakai |
|---|---|---|
| (default, inline) | Lambda di-inline ke pemanggil | Mayoritas kasus |
noinline | Lambda tetap jadi objek | Ingin menyimpan atau meneruskan lambda |
crossinline | Lambda tidak boleh non-local return | Lambda dipanggil dari context lain |
reified T | Type parameter tersedia saat runtime | Perlu cek is T atau T::class |
Manfaat dan Biaya Inline #
Inline mengurangi overhead alokasi lambda, tetapi meningkatkan ukuran bytecode — setiap pemanggilan function inline menyisipkan salinan body. Untuk function yang dipanggil banyak atau berada di hot path, inline memberi manfaat nyata. Untuk function yang jarang dipanggil atau berbody besar, inline bisa membengkakkan ukuran binary.
Referensi Lanjutan #
- Inline functions
— panduan resmi
inline,noinline,crossinline,reified - Higher-order functions and lambdas — lambda yang menjadi target inlining
Penutup #
Inline function adalah optimasi yang membuat Kotlin ringan untuk pemrograman fungsional. Dengan menyisipkan body ke pemanggilan, kompilator menghindari alokasi lambda dan membuka fitur seperti reified. Modifikator noinline dan crossinline memberi kontrol halus untuk kasus khusus. Selanjutnya, kita akan beralih ke topik yang berbeda namun saling melengkapi — callable references, yaitu cara merujuk ke function yang sudah ada tanpa membungkusnya dengan lambda.