Kotlin进阶实战
上QQ阅读APP看书,第一时间看更新

3.2.7 换个角度看Lambda表达式

Kotlin的代码最终还是会编译成.class文件,由JVM进行加载。

1.示例1

我们曾经讲过,sum这个函数本质上实现了kotlin.jvm.functions.Function2接口,即:

如图3-4所示,可以查看一下Kotlin Bytecode,会发现它确实是这样的。

图3-4 查看Kotlin函数的字节码

如图3-5所示,再来查看sum(3, 5)的使用,发现它调用了Function2的invoke()方法。

图3-5 sum(3, 5)函数的字节码

换一种工具,如图3-6所示,使用JD-GUI将上述Kotlin代码反编译成Java代码会更加清晰。

图3-6 使用JD-GUI进行反编译

有多种方式可以反编译成字节码,例如使用IDEA自带的工具Tools->Kotlin->Show Kotlin Bytecode,或者使用javap命令反编译.class文件,亦或者使用BytecodeViewer反编译.class文件,都能够将Kotlin的代码反编译成字节码。有时字节码看不清晰,反编译成Java代码效果会更好。

2.示例2

下面是使用filter、forEach的例子,它们都是高阶函数。

如图3-7所示,反编译成Java的代码之后,会发现并没有实现FunctionN接口。

图3-7 反编译高阶函数

这是因为在Kotlin的filter、forEach函数中都使用了inline,表明这些函数是内联函数。所以,这些函数不需要实例化FunctionN接口,内联函数的特性将会在第4章讲述。

Lambda表达式会实现一个FunctionN接口,N的大小由表达式的参数个数决定。在Kotlin 1.3之前不能大于23个,只能是0~22,在Kotlin 1.3之后放宽了限制。

如果Lambda表达式中使用函数作为参数,并且整个高阶函数使用inline修饰,Lambda表达式就不必实现FunctionN接口。