Kotlin 内联函数详解及实例

Kotlin 内联函数详解及实例

概述

在说内联函数之前,先说说函数的调用过程。

调用某个函数实际上将程序执行顺序转移到该函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。也就是通常说的压栈和出栈。因此,函数调用要有一定的时间和空间方面的开销。那么对于那些函数体代码不是很大,又频繁调用的函数来说,这个时间和空间的消耗会很大。

那怎么解决这个性能消耗问题呢,这个时候需要引入内联函数了。内联函数就是在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来直接进行替换。显然,这样就不会产生转去转回的问题,但是由于在编译时将函数体中的代码被替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间代销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。

inline

在Kotlin中,使用inline修饰符标记内联函数,既会影响到函数本身, 也影响到传递给它的Lambda表达式,这两者都会被内联到调用处。

例如:

inline fun lock<T>(lock: Lock, body: () -> T): T {
// ...
}

编译器可以直接产生下面的代码, 而不必为参数创建函数对象, 然后再调用这个参数指向的函数:

l.lock()
try {
  foo()
}
finally {
  l.unlock()
}

noinline

如果一个内联函数的参数中有多个 Lambda 表达式, 而你只希望内联其中的一部分, 你可以对函数的一部分参数添加 noinline 标记:

inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
  // ...
}

可内联的 Lambda 表达式只能在内联函数内部调用, 或者再作为可内联的参数传递给其他函数, 但noinline 的 Lambda 表达式可以按照我们喜欢的方式任意使用: 可以保存在域内, 也可以当作参数传递, 等等。

非局部返回(Non-local return)

在Kotlin中, 使用无限定符的通常的return语句, 只能用来退出一个有名称的函数, 或匿名函数. 这就意味着, 要退出一个Lambda表达式, 我们必须使用一个 标签, 无标签的 return 在 Lambda 表达式内是禁止使用的, 因为 Lambda 表达式不允许强制包含它的函数返回:

fun foo() {
  ordinaryFunction {
    return // 错误: 这里不允许让 `foo` 函数返回
  }
}

如果 Lambda 表达式被传递去的函数是内联函数, 那么 return 语句也可以内联, 因此 return 是允许的。

fun foo() {
  inlineFunction {
    return // OK: 这里的 Lambda 表达式是内联的
  }
}

注:

有些内联函数可能并不在自己的函数体内直接调用传递给它的 Lambda 表达式参数, 而是通过另一个执行环境来调用, 比如通过一个局部对象, 或者一个嵌套函数. 这种情况下, 在 Lambda 表达式内, 非局部的控制流同样是禁止的. 为了标识这一点, Lambda 表达式参数需要添加 crossinline修饰符。

inline fun f(crossinline body: () -> Unit) {
  val f = object: Runnable {
    override fun run() = body()
  }
  // ...
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Kotlin 基础教程之异常

    Kotlin 基础教程之异常 概述 在Kotlin-null的处理里提到的NPE,它就是一个异常.而,异常是程序运行过程中出现的错误.在Kotlin中,所有的异常都继承于Throwable.对于每一个异常而言,它不仅仅包括异常的信息,还可以选择性包括异常的原因,而其原因也是一个异常的实例. 抛出异常 使用 throw表达式抛出异常: throw MyException("Hi There!") 捕获异常 如果在函数内部抛出了异常(或者在函数内部调用的其他函数抛出了异常),这个函数将在抛

  • Kotlin 基本语法实例详解

    基本语法示例 实例代码: package com.stone.basic.syntax /** * desc : * author: stone * email : aa86799@163.com * time : 27/05/2017 11 01 */ class BasicSyntax { //Function having two Int parameters with Int return type: public fun sum(a: Int, b: Int): Int {//访问修饰

  • Kotlin 泛型详解及简单实例

     Kotlin 泛型详解 概述 一般类和函数,只能使用具体的类型:要么是基本类型,要么是自定义的类.如果要编写可以应用于多种类型的代码,这种刻板的约束对代码的限制很大.而OOP的多态采用了一种泛化的机制,在SE 5种,Java引用了泛型.泛型,即"参数化类型".一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参.那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用

  • Kotlin 基础教程之反射

    Kotlin 基础教程之反射 概述 反射是语言与库中的一组功能, 可以在运行时刻获取程序本身的信息.在Kotlin中,不仅可以通过发射获取类的信息,同时可以获取函数和属性的信息.也就是说,在在运行时刻得到一个函数或属性的名称和数据类型) 可以通过简单的函数式, 或交互式的编程方式实现. 在Java平台上, 使用反射功能所需要的运行时组件是作为一个单独的JAR文件发布的( kotlinreflect.jar). 这是为了对那些不使用反射功能的应用程序, 减少其运行库的大小. 如果你需要使用反射,

  • Kotlin编写Android适配器Adapter

    说好今天要写一个使用Kotlin写Adapter的列子,我想了半天也没有组织好语言,直接上代码吧,有一定Android基础的小伙伴肯定是能看的懂的 package com.example.administrator.kotlintest import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import and

  • Kotlin null的处理详解

    Kotlin null的处理详解 NullPointerException,俗称NPE,不管菜鸟还是老鸟们,都是不可避免,经常遇到的一个异常,解释起来很简单,就"空指针"三个字.总是在一次不小心,而掉进这个陷阱里.Kotlin 的设计目标就是希望消除代码中 null 引用带来的危险, 也就是所谓的造成十亿美元损失的大错误. NPE的原因 尽管Kotlin希望消除代码中的NPE,我们总是不小心,总会不小心又掉进NPE的陷阱,下面是可能NPE的原因: 明确调用 throw NullPoin

  • Kotlin this详解及实例

    Kotlin this详解及实例 为了表示当前函数的接收者(receiver), 们使用this表达式: 在类的成员函数中,this指向这个类的当前对象实例: 在扩展函数中,或带接收者的函数字面值(function literal) 中, this 代表调用函数时, 在点号左侧传递的接收者参数: 如果this没有限定符,那么它指向包含当前代码的最内层范围.如果想要指向其他范围内的this,需要使用标签限定符. 带限定符的this 为了访问更外层范围(比如 类, 或 扩展函数, 或有标签的 带接受

  • Kotlin 内联函数详解及实例

    Kotlin 内联函数详解及实例 概述 在说内联函数之前,先说说函数的调用过程. 调用某个函数实际上将程序执行顺序转移到该函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方.这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行.也就是通常说的压栈和出栈.因此,函数调用要有一定的时间和空间方面的开销.那么对于那些函数体代码不是很大,又频繁调用的函数来说,这个时间和空间的消耗会很大. 那怎么解决这个性能消耗问题呢,这个时候

  • C++ inline内联函数详解

    函数是一个可以重复使用的代码块,CPU 会一条一条地挨着执行其中的代码.CPU 在执行主调函数代码时如果遇到了被调函数,主调函数就会暂停,CPU 转而执行被调函数的代码:被调函数执行完毕后再返回到主调函数,主调函数根据刚才的状态继续往下执行. 一个 C/C++ 程序的执行过程可以认为是多个函数之间的相互调用过程,它们形成了一个或简单或复杂的调用链条,这个链条的起点是 main(),终点也是 main().当 main() 调用完了所有的函数,它会返回一个值(例如return 0;)来结束自己的生

  • C++ 内联函数详解

    目录 一.C++ 内联函数 1.内联 2.语法 3.评价 总结 一.C++ 内联函数 1.内联 C 语言中有宏函数的概念.宏函数的特点是内嵌到调用代码中去,避免了函数调用的开销.但是由于宏函数的处理发生在预处理阶段,缺失了语法检测和有可能带来的语意差错. 2.语法 C++提供了 inline 关键字,实现了真正的内嵌. 宏函数 VS inline函数 #include <iostream> #include <string.h> using namespace std; //优点:

  • Kotlin 的注解类详解及实例

    Kotlin 的注解类详解及实例 注解声明 注解是将元数据附加到代码的方法.要声明注解,请将 annotation 修饰符放在类的前面: annotation class Fancy 注解的附加属性可以通过用元注解标注注解类来指定: @Target 指定可以用 该注解标注的元素的可能的类型(类.函数.属性.表达式等): @Retention 指定该注解是否 存储在编译后的 class 文件中,以及它在运行时能否通过反射可见 (默认都是 true): @Repeatable 允许 在单个元素上多次

  • R语言函数详解及实例用法

    函数是一组组合在一起以执行特定任务的语句. R 语言具有大量内置函数,用户可以创建自己的函数. 在R语言中,函数是一个对象,因此R语言解释器能够将控制传递给函数,以及函数完成动作所需的参数. 该函数依次执行其任务并将控制返回到解释器以及可以存储在其他对象中的任何结果. 函数定义 使用关键字函数创建 R 语言的函数. R 语言的函数定义的基本语法如下 function_name <- function(arg_1, arg_2, ...) { Function body } 函数组件 函数的不同部

  • COM组件中调用JavaScript函数详解及实例

    COM组件中调用JavaScript函数详解及实例 要求是很简单的,即有COM组件A在IE中运行,使用JavaScript(JS)调用A的方法longCalc(),该方法是一个耗时的操作,要求通知IE当前的进度.这就要求使用回调函数,设其名称为scriptCallbackFunc.实现这个技术很简单: 1 .组件方(C++) 组件A 的方法在IDL中定义: [id(2)] HRESULT longCalc([in] DOUBLE v1, [in] DOUBLE v2, [in, optional

  • 对python中的for循环和range内置函数详解

    如下所示: 1.for循环和range内置函数配合使用 range函数生成一个从零开始的列表, range(4)表示list:0123 range(1,11,2)表示从1开始到11-1为止步长为2的list:13579 即range(i)表示从0开始到i-1的列表,range(m,n)表示从m开始到n-1的列表,range(m,n,t)表示从m开始步长为t到n-1的列表 ''' print('第一次循环输出:') for i in range(4): print(i) print('第二次循环输

  • SQL Server COALESCE函数详解及实例

    SQL Server COALESCE函数详解 很多人知道ISNULL函数,但是很少人知道Coalesce函数,人们会无意中使用到Coalesce函数,并且发现它比ISNULL更加强大,其实到目前为止,这个函数的确非常有用,本文主要讲解其中的一些基本使用:  首先看看联机丛书的简要定义: 返回其参数中第一个非空表达式语法: COALESCE ( expression [ ,...n ] ) 如果所有参数均为 NULL,则 COALESCE 返回 NULL.至少应有一个 Null 值为 NULL

  • Python函数的作用域及内置函数详解

    目录 1.函数的作用域 2.函数的调用详解 3.内置函数 总结 1.函数的作用域 -- 内置 -- 全局,顶格写 -- 局部,函数内部 a = 34 #全局变量 def run(): b = 44 #局部变量 print(a) print(b) #不可以直接调用局部变量,报错 运行结果: c = 12 def run(a): print(a) b = 33 run(5) # 一个全局变量c # 两个局部变量a,b # 函数的参数也是局部变量 运行结果: 5 局部 VS 全局 -- 局部空间(函数

  • Python中函数的基本定义与调用及内置函数详解

    前言 函数function是python编程核心内容之一,也是比较重要的一块.首先我们要了解Python函数的基本定义: 函数是什么? 函数是可以实现一些特定功能的小方法或是小程序.在Python中有很多内建函数,当然随着学习的深入,你也可以学会创建对自己有用的函数.简单的理解下函数的概念,就是你编写了一些语句,为了方便使用这些语句,把这些语句组合在一起,给它起一个名字.使用的时候只要调用这个名字,就可以实现语句组的功能了. 语法如下: # 定义方式 : def functionname([pa

随机推荐