inline function — derleme zamanında fonksiyon gövdesinin doğrudan her çağrı noktasına yerleştirildiği bir Kotlin mekanizmasıdır. Bu, lambda parametreleri için anonim sınıflar ve nesneler oluşturmanın ek yükünü ortadan kaldırır. Kotlin Documentation, 2025'e göre, inline anahtar kelimesi özellikle yüksek mertebeden fonksiyonlar için etkilidir; burada her lambda ekleme olmadan ayrı bir FunctionN nesnesi oluşturarak çöp toplayıcıyı yükler.
Önemli Noktalar
Inline fonksiyon, inline anahtar kelimesiyle işaretlenmiş bir fonksiyondur. Kotlin derleyicisi bunun için ayrı bir bayt kodu oluşturmaz — bunun yerine fonksiyon gövdesini doğrudan her çağrı noktasına kopyalar. Temel amaç, lambda ifadelerini kabul eden yüksek mertebeden fonksiyonları optimize etmektir, çünkü normal durumda her lambda anonim bir Function sınıfı nesnesi oluşturur.
JetBrains Tech Blog (2024)'e göre, Kotlin'de inline fonksiyon kullanımı, lambdaları yoğun olarak kullanan fonksiyonlarda oluşturulan nesne sayısını %40–60 oranında azaltabilir. Döngülerde ve yüksek yük operasyonlarında (sıralama, koleksiyon filtreleme) bu ölçülebilir bir performans artışı sağlar.
Inline olmadan, her lambda anonim bir sınıfa (veya sentezlenmiş bir işlevsel arayüz örneğine) derlenir. Değişkenleri yakalayan lambdalar için ek sarmalayıcı nesneler oluşturulur. Inline fonksiyonlar, tüm bu nesneleri derleme zamanında ortadan kaldırır ve sarmalayıcılar olmadan yerel değişkenlere erişen doğrudan kodla değiştirir.
Inline'ı yalnızca lambda parametreleri olan fonksiyonlar için kullanın — Kotlin derleyicisi, inline'ın fayda sağlamaması durumunda kendisi uyarır.
Fonksiyon bildiriminden önce inline anahtar kelimesini eklemeniz yeterlidir. Derleyici, çağrı noktalarında otomatik olarak fonksiyon gövdesini yerleştirir. Fonksiyonun kendisi, doğrudan çağrılmadığı durumlar için (örneğin, Java kodundan) bayt kodunda varlığını sürdürür.
inline fun Int.repeatAction(action: (Int) -> Unit) {
for (i in 0 until this) {
action(i)
}
}
// Çağrı — lambda kodu fonksiyon gövdesine eklenir
5.repeatAction { index ->
println("Index: $index")
}
Derlemeden sonra, yukarıdaki kod şuna eşdeğer olacaktır:
// Eklemeden sonra ne olur (şematik olarak):
val $this = 5
for (i in 0 until $this) {
println("Index: $i")
}
Lambda için hiçbir nesne oluşturulmaz — action kodu doğrudan yürütülür. İşte optimizasyonun özü budur: Function.invoke()'ı çağırmak yerine — lambda gövdesiyle kodun doğrudan eklenmesi.
Eklemeyi doğrulamak için IntelliJ IDEA'da Tools > Kotlin > Show Kotlin Bytecode'u açın ve Decompile'a tıklayın. Lambda ile repeatAction'ı çağırmak yerine, bir for döngüsüyle fonksiyon gövdesinin doğrudan eklendiğini göreceksiniz.
Kotlin'deki her lambda üç varyanttan birine derlenir. Birincisi — lambda değişken yakalamazsa, bildirildiği sınıfın statik bir yöntemi haline gelir. İkincisi — bir değişken yakalarsa, anonim bir sınıf oluşturulur. Üçüncüsü — birden çok değişken yakalarsa, yakalanan her değişken için alanları olan anonim bir sınıf oluşturulur.
| Lambda türü | Inline olmadan | Inline ile |
|---|---|---|
| Yakalama yok | Bir statik yöntem (yeniden kullanılır) | Tam ekleme, çağrı yok |
| 1 değişken yakalama | Anonim sınıf (bir nesne) | Tam ekleme, nesne yok |
| N değişken yakalama | N alanlı anonim sınıf | Tam ekleme, nesne yok |
| Özyinelemeli | Normal çağrı | inline yasak |
Android Performance Patterns (Google, 2024)'e göre, koleksiyonları yoğun kullanan uygulamalarda (filtreleme, sıralama, gruplama) inline fonksiyonlar tahsisatları %25–35 oranında azaltır. Etki özellikle Jetpack Compose'da belirgindir; burada her durum değişikliği birçok lambdayla yeniden oluşturmayı tetikler.
Normal bir fonksiyondaki lambda, dış fonksiyondan return yapamaz — yalnızca lambdanın kendisinden yerel dönüş (return@label aracılığıyla) mümkündür. Inline bir fonksiyonda lambda, çağıran fonksiyonun gövdesine eklenir, bu nedenle yerel olmayan dönüş mümkün hale gelir: lambda içindeki bir return, dış fonksiyonu sonlandırır.
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 }
// Lambdadaki return, processNumbers()'dan null döndürür
}
Yerel olmayan dönüş erken sonlandırma için kullanışlıdır ancak hatalara yol açabilir. Lambda yerel olmayan bir bağlamda kullanılırsa (bir değişkende saklanırsa), yerel olmayan dönüş bir RuntimeException'a neden olur. Kotlin derleyicisi, bu tür bir saklama girişiminde uyarı verir.
Bir fonksiyonun birden çok lambda parametresi olduğunda, bazen yalnızca bazılarını eklemek gerekir. Bunun için noinline kullanılır — belirli bir lambda parametresinin eklenmesini engeller ve onu normal bir Function nesnesi olarak bırakır.
crossinline değiştiricisi ters sorunu çözer: lambda eklenir, ancak yerel olmayan dönüş yasaktır. Bu, lambda başka bir lambda içinde veya return'e izin verilmeyen bir bağlamda kullanıldığında gereklidir (örneğin, bir Runnable'a geçirildiğinde).
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 bir değişkende saklanabilir veya başka yere aktarılabilir
val errorHandler = { e: Exception -> log(e.message) }
processWithCallback("input", { println(it) }, errorHandler)
Örnekte, onSuccess crossinline olarak işaretlenmiştir — eklenecektir, ancak içinde return kullanılamaz. onError noinline olarak işaretlenmiştir — eklenmez, bu nedenle nesne olarak geçirilebilir, bir sınıf alanında saklanabilir veya dinleyici olarak kullanılabilir.
Inline fonksiyonların sınırlamaları vardır. Özyinelemeli inline fonksiyonlar yasaktır — derleyici hata döndürür. Inline fonksiyonlar, başka bir modülde bildirilmişlerse private veya internal görünürlüğe sahip olamaz, ancak bu, ekleme mekanizmasının kendisiyle değil, görünürlükle ilgili bir sınırlamadır.
Gövde kopyalandığından, her inline fonksiyon çağrısıyla bayt kodu boyutu artar. Kotlin Coding Conventions (JetBrains, 2025)'e göre, inline'ın yalnızca 10–15 satıra kadar olan fonksiyonlar için kullanılması önerilir. Büyük fonksiyonlar için, lambda eklemenin faydası APK boyutundaki artışla geçersiz kılınabilir (Android'de 64K yöntem sınırı nedeniyle kritiktir).
// Önerilen uygulama
inline fun withLock(lock: Lock, action: () -> T): T {
lock.lock()
try {
return action()
} finally {
lock.unlock()
}
}
// Büyük fonksiyonlar için önerilmez
inline fun largeComputation(...) { // kötü — gövde >50 satır
// 50 satırdan fazla — normal bir fonksiyona çıkarmak daha iyi
}
Kitaplıklardaki genel inline fonksiyonlar dikkat gerektirir: bir inline fonksiyonun gövdesi değişirse, tüm istemcilerin yeniden derlenmesi gerekir. JetBrains, bir modül içinde uyumluluğu korumak için inline fonksiyonlardan çağrılan üyeler için @PublishedApi internal kullanılmasını önerir.
Sıkça Sorulan Sorular
Evet, inline genişletme fonksiyonu kısıtlama olmadan çalışır. Örneğin: inline fun String.transform(block: (Char) -> Char): String. Genişletme, ekleme yeteneğini etkilemez — derleyici onu normal bir inline fonksiyon gibi işler.
Fonksiyon lambda parametreleri kabul etmiyorsa — inline avantaj sağlamaz. Kotlin derleyicisi bir uyarı verir: “Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types.” Ayrıca, bayt kodu büyümesi nedeniyle inline büyük fonksiyonlar için zararlıdır.
inline — fonksiyon gövdesini çağrı noktasına ekleyen bir fonksiyon değiştiricisidir. @JvmInline (value class) — derleme zamanında değerleriyle değiştirilen sarmalayıcı sınıflar için bir mekanizmadır. Farklı kavramlar: inline çağrıları optimize eder, value class veri temsilini optimize eder.
Hayır, suspend fonksiyonları, Continuation ile bir durum makinesine derlendikleri için inline olamaz. Ancak, bir inline fonksiyon, crossinline ile bir parametre olarak suspend lambda kabul edebilir. Bu genellikle coroutine'lerde kullanılır: inline fun launch(block: suspend CoroutineScope.() -> Unit).
Evet, inline fonksiyonlar hata ayıklamayı zorlaştırır çünkü fonksiyon gövdesi çağrılmaz, çağrı noktasına eklenir. Yığın izleri uzar, kesme noktaları çalışır ancak beklenmeyen konumlar gösterebilir. JetBrains, inline olmadan hata ayıklamayı ve yalnızca release yapılarında etkinleştirmeyi önerir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun