Mobile Development
Kotlin
Subjective
Oct 04, 2025
What are inline functions, reified generics, and their performance implications?
Detailed Explanation
Inline functions copy function body to call site, eliminating overhead and enabling reified type parameters.\n\n**Basic inline functions:**\n\ninline fun measureTime(block: () -> Unit) {\n val start = System.currentTimeMillis()\n block()\n val end = System.currentTimeMillis()\n println("Time taken: ${end - start}ms")\n}\n\n// Usage - block() call is inlined\nmeasureTime {\n Thread.sleep(1000)\n}\n\n// Compiled equivalent:\nval start = System.currentTimeMillis()\nThread.sleep(1000)\nval end = System.currentTimeMillis()\nprintln("Time taken: ${end - start}ms")\n\n\n**Reified type parameters:**\n\n// Without reified - type erasure\nfun isInstance(value: Any, clazz: Class): Boolean {\n return clazz.isInstance(value)\n}\n\n// With reified - type available at runtime\ninline fun isInstance(value: Any): Boolean {\n return value is T\n}\n\n// Usage\nval isString = isInstance("Hello") // true\nval isInt = isInstance("Hello") // false\n\n\n**Practical reified examples:**\n\n// JSON parsing\ninline fun Gson.fromJson(json: String): T {\n return fromJson(json, T::class.java)\n}\n\nval user = gson.fromJson(jsonString)\n\n// Type-safe casting\ninline fun Any?.safeCast(): T? {\n return this as? T\n}\n\nval string = obj.safeCast()\n\n// Collection filtering\ninline fun List<*>.filterIsInstance(): List {\n return filter { it is T }.map { it as T }\n}\n\nval strings = mixedList.filterIsInstance()\n\n\n**noinline and crossinline:**\n\ninline fun processData(\n data: String,\n noinline logger: (String) -> Unit, // Not inlined\n crossinline processor: (String) -> String // Inlined but no non-local returns\n) {\n logger("Processing: $data")\n \n val result = processor(data)\n \n // Can store noinline lambda in variable\n val storedLogger = logger\n \n // Cannot store crossinline lambda that allows returns\n // val storedProcessor = processor // Would cause compilation error if processor had returns\n}\n\n\n**Non-local returns:**\n\nfun processItems(items: List) {\n items.forEach { item ->\n if (item.isEmpty()) {\n return // Returns from processItems, not forEach\n }\n println(item)\n }\n println("Processing complete")\n}\n\n// With crossinline - prevents non-local returns\ninline fun List.forEachSafe(crossinline action: (T) -> Unit) {\n for (item in this) {\n action(item) // Cannot return from calling function\n }\n}\n\n\n**Performance implications:**\n\n**Benefits:**\n• Eliminates function call overhead\n• Reduces object allocations for lambdas\n• Enables reified generics\n• Better optimization opportunities\n• No boxing/unboxing for primitive parameters\n\n**Costs:**\n• Increases bytecode size (code duplication)\n• Longer compilation time\n• Can cause method size limits in extreme cases\n\n**Performance measurement:**\n\n// Regular function\nfun regularMap(list: List, transform: (T) -> R): List {\n val result = mutableListOf()\n for (item in list) {\n result.add(transform(item))\n }\n return result\n}\n\n// Inline function\ninline fun inlineMap(list: List, transform: (T) -> R): List {\n val result = mutableListOf()\n for (item in list) {\n result.add(transform(item))\n }\n return result\n}\n\n// Benchmark shows inline version is faster for simple operations\nval numbers = (1..1000000).toList()\n\nmeasureTime {\n regularMap(numbers) { it * 2 } // Creates lambda object\n}\n\nmeasureTime {\n inlineMap(numbers) { it * 2 } // No lambda object, inlined multiplication\n}\n\n\n**When to use inline:**\n• Functions with lambda parameters\n• Small, frequently called functions\n• When you need reified generics\n• Performance-critical code paths\n\n**When to avoid inline:**\n• Large functions (increases bytecode size)\n• Functions with complex logic\n• Recursive functions (not allowed)\n• When function is rarely called
Discussion (0)
No comments yet. Be the first to share your thoughts!
Share Your Thoughts