美文网首页
inline noinline crossinline

inline noinline crossinline

作者: 长点点 | 来源:发表于2023-05-28 16:58 被阅读0次

    除了crossinline和noinline,Kotlin中还有一个和inline相关的关键字,就是reified。这些关键字的作用区别,应用场景如下:

    • inline: 用于修饰函数,表示这个函数可以被内联,即在编译时将函数的调用替换为函数的实际代码,从而避免函数调用的开销和额外的内存分配。inline函数通常用于高阶函数,即接收或返回另一个函数的函数,例如map、filter等。inline函数可以提高高阶函数的性能,同时也可以支持非局部返回,即在lambda表达式中使用return直接返回外层函数。
    • crossinline: 用于修饰inline函数的lambda参数,表示这个lambda参数不能使用非局部返回,即不能在lambda表达式中使用return直接返回外层函数。crossinline通常用于当inline函数将lambda参数传递给另一个执行上下文时,例如一个局部对象或一个嵌套函数。如果不使用crossinline,可能会导致非预期的行为或编译错误。
    • noinline: 用于修饰inline函数的lambda参数,表示这个lambda参数不会被内联,即保持原样作为一个普通的函数参数。noinline通常用于当inline函数不需要内联所有的lambda参数时,例如当某些lambda参数很少被调用或很复杂时。如果不使用noinline,可能会导致性能下降或代码膨胀。
    • reified: 用于修饰inline函数的泛型参数,表示这个泛型参数可以被具体化,即在运行时可以获取到它的真实类型。reified通常用于当inline函数需要根据泛型参数做一些操作时,例如类型判断、类型转换、反射等。如果不使用reified,可能会导致类型擦除或编译错误。

    下面是一些使用这些关键字的代码示例:

    • inline: 使用inline修饰一个高阶函数:
    // 定义一个接收两个Int参数和一个(Int, Int) -> Int类型的lambda参数的内联函数
    inline fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
        // 调用lambda参数并返回结果
        return operation(a, b)
    }
    
    // 调用内联函数,并传入两个Int值和一个lambda表达式
    val result = calculate(10, 20) { x, y -> x + y }
    
    // 编译后相当于
    val result = 10 + 20
    
    • crossinline: 使用crossinline修饰一个传递给另一个执行上下文的lambda参数:
    // 定义一个接收一个() -> Unit类型的lambda参数的内联函数
    inline fun runOnThread(crossinline action: () -> Unit) {
        // 将lambda参数传递给一个线程对象
        val thread = Thread {
            // 在线程中调用lambda参数
            action()
        }
        // 启动线程
        thread.start()
    }
    
    // 调用内联函数,并传入一个lambda表达式
    runOnThread {
        // 在线程中打印一条信息
        println("Hello from thread")
    }
    
    // 如果不使用crossinline,就不能在lambda表达式中使用return直接返回外层函数
    runOnThread {
        // 尝试在线程中返回外层函数
        return // 编译错误:return is not allowed here
    }
    
    • noinline: 使用noinline修饰一个不需要被内联的lambda参数:
    // 定义一个接收两个() -> Unit类型的lambda参数的内联函数
    inline fun runBoth(noinline action1: () -> Unit, action2: () -> Unit) {
        // 调用第一个lambda参数
        action1()
        // 调用第二个lambda参数
        action2()
    }
    
    // 调用内联函数,并传入两个lambda表达式
    runBoth({
        // 打印一条信息
        println("Hello")
    }, {
        // 返回外层函数
        return // 正常返回
    })
    
    // 如果不使用noinline,就不能将lambda参数作为另一个非内联函数的参数
    fun runLater(action: () -> Unit) {
        // 延迟一秒后调用action
        Handler().postDelayed(action, 1000)
    }
    
    runBoth({
        // 将第一个lambda参数作为另一个非内联函数的参数
        runLater(it) // 编译错误:non-local return not allowed
    }, {
        // 打印一条信息
        println("World")
    })
    
    • reified: 使用reified修饰一个需要具体化的泛型参数:
    // 定义一个接收一个Any类型的参数和一个泛型类型T的内联函数
    inline fun <reified T> isA(value: Any) = value is T
    
    // 调用内联函数,并传入一个Any类型的值和一个泛型类型String
    val result = isA<String>("Hello")
    
    // 编译后相当于
    val result = "Hello" is String
    
    // 如果不使用reified,就不能根据泛型类型做类型判断
    fun <T> isA(value: Any) = value is T // 编译错误:Cannot check for instance of erased type: T
    
    

    相关文章

      网友评论

          本文标题:inline noinline crossinline

          本文链接:https://www.haomeiwen.com/subject/yrsdedtx.html