Kotlin与Java比较:内联函数

2018-12-10  本文已影响16人  程序引力

前言

Kotlin作为JVM系的语言,起源于Java又不同于Java。通过在语言层面比较两者的区别,可以使得开发者能够快速学习,融会贯通。

内联函数概念

内联函数主要是指在编译或加载时被扩展的函数。以一个简单的例子进行理解:

fun main(){
    x = 1
    y = 2
    z = add(x, y)
}

add(x, y){
    return x + y
}

如果将add方法作为内联函数处理,则add方法会在被调用的地方进行扩展,进而变成如下形式:

fun main(){
    x = 1
    y = 2
    z = x + y
}

也就是说,这像是将内联函数add的代码复制到了调用的地方。

那为何要这么做呢?因为在程序语言中,调用方法需要将方法入栈,然后执行点会移动到栈中的方法处,执行完方法后,方法出栈,回到原来调用方法的地方继续执行。这一过程需要有时间和空间的开销。如果同一个方法被调用得非常频繁,那么会对性能造成一定影响。此时如果将该方法以内联函数的形式进行处理,即在编译或加载时最对进行展开,则避免了这部分的开销。

内联函数使用

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

inline 修饰符影响函数本身和传给它的 lambda 表达式:所有这些都将内联到调用处。
内联函数的适用场景:

内联函数优点:可能提升性能
内联函数缺点:生成的代码增加

内联的 lambda 表达式只能在内联函数内部调用或者作为可内联的参数传递, 但是对于不希望被内联的函数,可以使用关键字noinline进行声明。这些函数可以以任何我们喜欢的方式操作:存储在字段中、传送它等等。

内联函数返回

由于Java在语言层面不支持内联函数,故此部分内容以Kotlin为基础进行介绍。
若要在lambda表达式中返回一个值,有两种方式,分别是返回表达式中最后一个语句,或者通过return添加标签的形式,例如:

ints.filter {
    val shouldFilter = it > 0 
    shouldFilter
}

ints.filter {
    val shouldFilter = it > 0 
    return@filter shouldFilter
}

在Kotlin中,lambda表达式内部禁止仅使用return进行返回,即不添加任何标签。因为 lambda 表达式不能使包含它的函数返回:

fun foo() {
    ordinaryFunction {
        return // 错误:不能使 `foo` 在此处返回
    }
}

但是如果 lambda 表达式传给的函数是内联的,该 return 也可以内联,所以它是允许的:

fun foo() {
    inlined {
        return // OK:该 lambda 表达式是内联的
    }
}

这种返回(位于 lambda 表达式中,但退出包含它的函数)称为非局部返回。

内联属性

inline 修饰符可用于没有幕后字段的属性的访问器。 可以标注独立的属性访问器:

val foo: Foo
    inline get() = Foo()

var bar: Bar
    get() = ……
    inline set(v) { …… }

同时,也可以标注整个属性,将它的两个访问器都标记为内联:

inline var bar: Bar
    get() = ……
    set(v) { …… }

在调用处,内联访问器如同内联函数一样内联。

上一篇 下一篇

猜你喜欢

热点阅读