Historie der Frage:
Mit dem Anstieg der Beliebtheit der funktionalen Programmierung und von Lambda-Ausdrücken in der JVM entstand das Problem des Overheads durch anonyme Objekte und zusätzliche Methodenaufrufe. In Java tritt dies bei der Verwendung funktionaler Schnittstellen auf. In Kotlin wurde das Schlüsselwort inline eingeführt, um zusätzliche Allokationen beim Übergeben von Lambda-Funktionen zu vermeiden.
Problem:
Der Aufruf einer Funktion mit Lambda-Parametern erzeugt anonyme Objekte im Heap und erhöht die Stack-Tiefe, was die Ausführungsgeschwindigkeit des Codes verlangsamt, insbesondere bei intensiver Nutzung in Schleifen und geschachtelten Aufrufen.
Lösung:
Kotlin ermöglicht es, eine Funktion mit dem Modifikator inline zu deklarieren, nach dem der Funktionskörper und die übergebenen Lambdas beim Kompilieren direkt an der Aufrufstelle eingefügt werden. Dies erlaubt es dem Compiler, auf zusätzliche Allokationen zu verzichten und die Leistung zu steigern, insbesondere für kurze, häufig aufgerufene Funktionen (z. B. Filterung von Sammlungen).
Beispielcode:
inline fun <T> Iterable<T>.myFilter(predicate: (T) -> Boolean): List<T> { val result = mutableListOf<T>() for (item in this) if (predicate(item)) result.add(item) return result } val filtered = listOf(1, 2, 3, 4).myFilter { it % 2 == 0 } println(filtered) // [2, 4]
Hauptmerkmale:
noinline und crossinline zu verwenden, um das Inlining einzelner Lambdas zu steuern.Kann ich eine Inline-Funktion mit jedem funktionalen Parameter oder vom generischen Typ T verwenden?
Nein, Inline-Funktionen sparen in erster Linie bei den Aufrufkosten von Lambda-Parametern, aber der generische Parameter selbst (z. B. T) wird nicht inlined — dafür ist der reified Modifikator erforderlich. Für einfache T ohne reified wird die Typinformation während des Kompilierungsprozesses gelöscht.
Was passiert, wenn in einer Inline-Funktion eine Closure auf eine Variable aus dem äußeren Scope deklariert wird?
Variablen aus dem äußeren Scope werden in den inline-Ausdruck kopiert. Alle Zugriffe auf sie werden so funktionieren, als wäre der Code tatsächlich eingefügt. Dies kann zu unerwartetem Verhalten führen, wenn man keine Nebeneffekte erwartet.
Kann ich eine Inline-Funktion aus Java-Code aufrufen?
Ja, aber sie wird als normale Funktion kompiliert, und der Java-Code sieht keine Vorteile des Inlinings. Kotlin erzielt die Optimierung nur bei der Verwendung von Inline-Funktionen im Kotlin-Code.
return in Inline-Lambdas — inkorrekte FlusskontrolleEin Entwickler inlinet eine lange Funktion mit mehreren Lambda-Filtern und Nachbearbeitungen in der Hoffnung auf Beschleunigung. Der Code wird lange kompiliert, das endgültige APK/RAR/DEX wird erheblich größer, ohne dass es einen Geschwindigkeitszuwachs gibt.
Vorteile:
Nachteile:
Eine kleine Inline-Funktion für kurze Array-Filter wird implementiert, die Hunderte von Malen in einer heißen Schleife aufgerufen wird — die Ausführungszeit ist kritisch wichtig. Der Speicherbedarf ist minimal, da die Lambda kein anonymes Objekt erstellt.
Vorteile:
Nachteile: