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,进而提高运行时的性能。