Skip to Content
Kotlin📘 Ngôn ngữ Kotlin🚀 Inline Functions

Inline Functions

🎯 Mục tiêu: Tối ưu hiệu suất cho Higher-Order Functions bằng cách sử dụng inline, noinline, crossinlinereified.


🚀 Vấn đề hiệu năng

Mỗi khi bạn tạo một lambda expression, Kotlin (trên JVM) thường tạo một object Function ẩn. Nếu dùng lambda trong vòng lặp hoặc gọi quá nhiều, nó gây áp lực lên bộ nhớ (memory allocation) và Garbage Collector.

inline sinh ra để giải quyết vấn đề này.


💡 Inline hoạt động thế nào?

Khi bạn đánh dấu một hàm là inline, Compiler sẽ copy code của hàm đó và copy code của lambda bỏ trực tiếp vào nơi gọi hàm, thay vì tạo object.

inline fun <T> measure(action: () -> T): T { val start = System.nanoTime() val res = action() val end = System.nanoTime() println("Time: ${end - start}ns") return res } fun main() { measure { println("Working...") } }

Code sau khi biên dịch sẽ (tương đương) như sau:

fun main() { val start = System.nanoTime() println("Working...") // Code của lambda được copy vào đây val end = System.nanoTime() println("Time: ${end - start}ns") }

Không có object function nào được tạo ra! 🎉


🚫 noinline

Nếu hàm inline nhận nhiều lambda, và bạn chỉ muốn inline một số cái, hãy dùng noinline cho những cái còn lại.

Bạn cần noinline nếu muốn gán lambda đó cho một biến hoặc truyền nó cho một hàm khác (không inline).

inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) { inlined() // Được copy code notInlined() // Vẫn là object, có thể gán biến val f = notInlined // OK }

❌ Non-local Returns & crossinline

Trong lambda thông thường, bạn không thể dùng return để thoát hàm bao ngoài. Nhưng với inline function, vì code được copy ra ngoài, bạn có thể return!

fun main() { measure { println("Start") return // ❌ Thoát luôn hàm main()!!! } println("End") // Dòng này sẽ KHÔNG được in ra }

Đây gọi là Non-local return.

Nếu bạn muốn cấm điều này (ví dụ lambda được chạy trong một thread khác hoặc context khác), hãy dùng crossinline.

inline fun executeAsync(crossinline action: () -> Unit) { Thread { action() // Không cho phép return non-local ở đây }.start() }

🧬 Reified Type Parameters

Một tính năng “thần thánh” của inline function: Reified Generics. Bình thường, Generic bị xóa kiểu tại runtime (Type Erasure). Bạn không thể check T::class hay is T.

Với inline + reified, bạn có thể!

inline fun <reified T> isType(value: Any): Boolean { return value is T // ✅ OK nhờ reified } fun main() { println(isType<String>("Hello")) // true println(isType<Int>("Hello")) // false }

Ứng dụng phổ biến trong Android (startActivity) hay JSON parsing:

// Thay vì: gson.fromJson(json, User::class.java) val user = gson.fromJson<User>(json)

✅ Checklist

  • Hiểu khi nào nên dùng inline (với HOF)
  • Biết sự khác biệt giữa inline và hàm thường
  • Cẩn thận với Non-local returns
  • Sử dụng reified để kiểm tra Generic type
Last updated on