何时在Kotlin中使用内联函数?
我知道一个内联函数可能会提高性能,并导致生成的代码增长,但我不知道什么时候使用它是正确的。
lock(l) { foo() }
编译器可以发出下面的代码,而不是为参数创建一个函数对象并生成一个调用。 ( 来源 )
l.lock() try { foo() } finally { l.unlock() }
但是我发现kotlin没有为非内联函数创建函数对象。 为什么?
/**non-inline function**/ fun lock(lock: Lock, block: () -> Unit) { lock.lock(); try { block(); } finally { lock.unlock(); } }
假设你创建一个更高阶的函数,它需要一个类型为() -> Unit
(无参数,无返回值)的lambda表达式,并像下面这样执行它:
fun nonInlined(block: () -> Unit) { println("before") block() println("after") }
按照Java的说法,这将转化为像这样(简化!):
public void nonInlined(Function block) { System.out.println("before"); block.invoke(); System.out.println("after"); }
而当你从Kotlin打电话给…
nonInlined { println("do something here") }
在这里, Function
一个实例将在这里被创建,它将代码包装在lambda中(同样,这被简化了):
nonInlined(new Function() { @Override public void invoke() { System.out.println("do something here"); } });
所以基本上,调用这个函数并传递一个lambda到它总是会创建一个Function
对象的实例。
另一方面,如果您使用inline
关键字:
inline fun inlined(block: () -> Unit) { println("before") block() println("after") }
当你这样称呼它时:
inlined { println("do something here") }
没有Function
实例会被创建,相反,围绕在内嵌函数中的block
调用的代码将被复制到调用站点,所以你会得到这样的字节码:
System.out.println("before"); System.out.println("do something here"); System.out.println("after");
在这种情况下,不会创建新的实例。