一、前置条件

  1. Kotlin中函数是顶层对象

    Kotlin中函数是一等公民。

Kotlin中的函数可以写在任何以.kt后缀的文件中。

https://gitee.com/yyqdata/TyporaImage/raw/master/PicGoImg/image-20220926151516797.png

  1. 使用工具反编译Kotlin代码

(1)Tools->Kotlin->Show kotlin byteCode->Decompile 如下图所示:

https://gitee.com/yyqdata/TyporaImage/raw/master/PicGoImg/image-20220926101329741.png

(2)点击Decompile后就可以得到对应的Java代码:

https://gitee.com/yyqdata/TyporaImage/raw/master/PicGoImg/image-20220926151620810.png

Kotlin中的顶层函数其实就是将对应的函数包裹上一层类,并将函数转成对应类的静态方法,如myFun()等,而匿名函数对象mFun则会转成静态属性对象,类型则根据函数参数自动生成 Function0…22 等内置函数对象类。

kotlin byteCode中并没有具体显示内置函数对象的实现,但是在 Decompile 之前是可以看到对应的函数 ByteCode 的,如下图所示:

https://gitee.com/yyqdata/TyporaImage/raw/master/PicGoImg/image-20220926153005165.png

  1. 扩展函数

    Kotlin中的重要特性之一:扩展一个类的新功能而无需继承该类或者使用像装饰者这样的设计模式。

扩展函数使用方法:

https://gitee.com/yyqdata/TyporaImage/raw/master/PicGoImg/image-20220927100021429.png

Person类中并没有定义run()方法,通过扩展可以让Person类对象具有该方法,同时可以在该方法中访问对应的非私有成员变量。Decode一下看看怎么实现的:

https://gitee.com/yyqdata/TyporaImage/raw/master/PicGoImg/image-20220927101310657.png

可以看到我们定义的Person类对象扩展函数反编译后并不是在对应的类中创建函数,而是在创建的文件类对象中创建静态方法run(Person $this$run),并且在无参函数中添加了一个Person类型的参数(Kotlin中很多语法如协程等都会在对应的函数中添加参数来实现某些功能),通过这个对象来访问对应的非私有成员变量及函数。

为什么是非私有呢?因为Kotlin中的属性会默认生成get/set方法,但是如果声明val则只会生成get方法。而属性的可见修饰符会作用在对应的get/set方法上,私有方法其他类无法访问。

  1. 闭包

    在 Kotlin 中有这样一个语法糖:当函数的最后一个参数是 lambda 表达式时,可以将 lambda 写在括号外。这就是它的闭包原则。