
4.1.1 inline的使用
1.示例1
在main函数中,分别使用内联函数和非内联函数打印一段文字。

其中nonInlined需要创建Function0对象,而使用了内联的inlined函数,不用再创建Function0对象,直接被复制到被调用处。
将上述代码反编译成Java代码之后,如图4-1所示。

图4-1 反编译内联和非内联函数
发现在main函数中直接使用了:
String str = "do something with inlined"; System.out.println(str);
2.示例2
对Closeable类进行扩展,让它支持Java的try-with-resources特性。其实,在Kotlin 1.2后已经在Closeable.kt中增加了扩展函数use(),和下面的代码类似:

这里用到了扩展函数(能够在不改变已有类的情况下,为某个类添加新的函数),这个特性会在4.3节详细介绍。
我们来看看在Kotlin中如何使用这个use()方法:

上述代码等价于以下Java代码:

Kotlin的代码节省了try...catch...finally语句,并自动关闭了文件输出流。
小结一下内联函数的特性:
· 内联函数中有函数类型的参数,那么该函数类型的参数默认也是内联的。除非显式使用noinline进行修饰,这样该函数类型就不再是内联的。
· 内联函数的优点是效率高、运行速度快。
· 内联函数的缺点是编译器会生成比较多的代码,所以内联函数不要乱用。
额外提一下,在Kotlin 1.5之后的内联类,使用value来修饰类,而不是使用inline进行修饰。
value class User(val name: String,val password:String)
需要注意:内联函数和内联类是有区别的。
如果业务逻辑需要围绕某种类型创建包装器,但是,由于额外的堆分配,它引入了运行时开销。此外,如果被包装的类型是原始类型,则性能损失会很糟糕,因为原始类型通常在运行时进行了大量优化,而它们的包装器没有任何特殊地处理。Kotlin为了解决这个问题,引入了内联类。
内联类是基于值的类的子集。在最终生成的字节码中被替换成其“包装”的value,进而提高运行时的性能。