MST

星途 面试题库

面试题:Kotlin内联函数与内联类之中等难度题

请简述Kotlin内联函数相比于普通函数的优势,并举例说明在什么场景下使用内联函数会带来性能提升。同时,解释一下内联函数中reified类型参数的作用和使用场景。
33.6万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试

Kotlin内联函数相比于普通函数的优势

  1. 减少函数调用开销:普通函数调用会有压栈、传参、执行函数体、出栈等开销。内联函数在编译时,函数体直接替换调用处,避免了这些开销,提升了性能,尤其是在频繁调用的情况下。
  2. 支持具体化类型参数:普通函数无法在运行时获取泛型参数的实际类型,而内联函数结合reified关键字可以做到。

性能提升场景举例

例如,一个高阶函数频繁被调用,且函数体逻辑简单的场景。

fun measureTime(block: () -> Unit): Long {
    val startTime = System.currentTimeMillis()
    block()
    return System.currentTimeMillis() - startTime
}

inline fun measureTimeInline(block: () -> Unit): Long {
    val startTime = System.currentTimeMillis()
    block()
    return System.currentTimeMillis() - startTime
}

fun main() {
    var totalTime = 0L
    for (i in 0 until 100000) {
        totalTime += measureTime {
            // 简单逻辑,比如打印或计算一个简单表达式
            println(i)
        }
    }
    println("普通函数总耗时: $totalTime")

    totalTime = 0L
    for (i in 0 until 100000) {
        totalTime += measureTimeInline {
            println(i)
        }
    }
    println("内联函数总耗时: $totalTime")
}

在上述例子中,measureTimeInline作为内联函数,由于函数体直接替换到调用处,没有函数调用开销,对于大量调用场景,性能会比普通的measureTime函数有明显提升。

内联函数中reified类型参数的作用和使用场景

  1. 作用reified关键字使内联函数能够在运行时获取泛型类型参数的实际类型,而普通函数的泛型类型参数在编译后会被擦除。
  2. 使用场景
    • 类型检查:例如在一个通用的filter函数中,可以在运行时检查集合元素的类型。
inline fun <reified T> List<*>.filterIsInstance(): List<T> {
    val result = mutableListOf<T>()
    for (element in this) {
        if (element is T) {
            result.add(element)
        }
    }
    return result
}

fun main() {
    val mixedList = listOf(1, "two", 3, "four")
    val intList = mixedList.filterIsInstance<Int>()
    println(intList)
}
- **反射操作**:当需要基于泛型类型进行反射操作时,`reified`类型参数可以提供实际类型信息。例如创建对象实例。
inline fun <reified T> createInstance(): T {
    return T::class.java.newInstance()
}

但需注意,createInstance函数中T::class.java.newInstance()这种反射方式在现代Java中已不推荐,只是用于说明基于reified进行反射操作的思路。实际可使用kotlin-reflect库结合reified进行更安全的反射实例创建。