Kotlin内联函数是否比Java匿名类更便宜?

时间:2017-05-19 01:05:31

标签: java kotlin

抬头:我从记忆中写下了一些内容,所以我的一些概念可能不正确。

Java具有编写匿名函数的能力。当您拥有某种事件的侦听器接口时,这非常有用。举个例子:

button.setOnClickListener(new View.OnClickListener(View v) {
    @Override
    public void onClick(View v) {
        // handle the action here
    }
});

匿名侦听器将被编译为类似OnClickListener$1.class的类。这是Java语言的基础设计决策。一切都是对象,甚至是匿名函数。

当您想要编写功能更强大的代码库时,这就成了一个问题。大量的匿名类会创建一个大的类计数,这在Android等受限平台上可能会出现问题。

在Kotlin中,从源代码的角度来看,函数是更先进的。我的问题是,Kotlin是否比Java使用匿名类更有效地将这些函数编译为字节代码,还是会遇到与Java中的大类计数相同的问题?

谢谢,

2 个答案:

答案 0 :(得分:11)

简短的回答是,Kotlin内联函数相当便宜。

当编译内联函数调用时,传递给调用的lambda将内联到函数体中,而函数体又在调用站点内联。这允许编译器不为lambda体生成任何其他类或方法。

Compilation of an inline function

关于Kotlin的the slides之一构造了@yole的编译。  不幸的是,我发现只有in Russian的记录。其他幻灯片也有一些兴趣,你可以在那里找到更多关于非内联lambda的内容。

通常,使用带有lambdas的内联函数的Kotlin代码比使用lambdas或Streams的相同Java代码工作得更快。所有代码绑定都是在编译时完成的,虚拟方法调用没有运行时开销,也没有增加方法计数,这对于Android来说很重要。

过度内联的缺点是代码大小增长:内联函数体的字节码的公共部分实际上在调用站点处重复。此外,内联使调试复杂化,因为代码的行号和调用堆栈将与源文件中的不同。虽然IDE支持可以在这里提供帮助。

我建议您自己尝试使用内联函数:您可以轻松地inspect the resulting bytecode;当然,对性能很重要的特定用例做一些基准测试。

答案 1 :(得分:2)

Kotlin有inline个关键字。如果你使用这个关键字,它不仅内联函数,而且你可以将lambda体视为嵌套的范围级别,这样你就可以return了!

示例(直接来自文档)

fun foo() {
    inlineFunction {
        return // OK: the lambda is inlined
    }
}

查看文档了解更多信息:

https://kotlinlang.org/docs/reference/inline-functions.html

编辑:

为了澄清您关于效果的确切问题,这是文档中的第一段:

  

使用高阶函数会产生某些运行时惩罚:每个函数都是一个对象,它捕获一个闭包,即在函数体中访问的那些变量。内存分配(包括函数对象和类)和虚拟调用都会引入运行时开销。

     

但似乎在很多情况下,可以通过内联lambda表达式来消除这种开销。

因此,我可以告诉它,它将内联函数并删除否则会产生的任何开销。

但是,这似乎只适用于您声明为inline的函数。