前言
为何写作本书
2018年,我受邀在“JetBrains开发者日—2018中国巡演”活动中做题为“如何优雅地使用Kotlin数据类”的分享。在准备这次分享时,我花了几天时间调研为Kotlin的数据类提供深复制能力的可行性,并给出了基于Kotlin反射和Java注解处理器(APT)的实现方案,也就是后来开源的DeepCopy项目。当时我尝试过编写一款编译器插件来实现这个需求,不过最终因为对Kotlin编译器的了解有限而未能如愿。
2021年,我受邀在Google开发者社区主办的“社区说”活动中做题为“Kotlin编译器插件:我们究竟在期待什么?”的分享。这一次,我花了两周时间初步基于Kotlin符号处理器(KSP)和编译器插件实现了数据类的深复制,整个过程充满了探索的乐趣。
为了加深对Kotlin编译器的认识,我基于Kotlin编译器插件完成了可以实现类似于Android的@IntDef功能的ValueDef编译器插件。事实上,ValueDef的功能更强大,@IntDef只会在代码编写时提供错误提示,而ValueDef除了会提供错误提示以外,还会在编译时报错。
与此同时,随着Kotlin符号处理器的开源和Jetpack Compose的发布,大家对Kotlin元编程的关注度也在逐步提升,但这方面的相关资料非常少。
于是,我向机械工业出版社的杨福川老师提出了把这些内容整理成书的想法,得到了他的肯定和支持。有了编写《深入理解Kotlin协程》[1]的经验,我很快就正式开始了这本书的写作。
本书主要特点
“元编程”是一个比较庞大的话题,本书主要介绍了生产实践中应用较为广泛的反射、Java注解处理器、Kotlin符号处理器、Kotlin编译器插件、Kotlin语法分析等元编程相关的内容。
与一般的语法知识不同,元编程相关的内容通常较为抽象。为了更好地让读者理解元编程相关的各项技术,本书提供了丰富的应用案例。这些案例相对成熟和完善,可以作为元编程项目的范本。
本书基本上遵循了基础知识介绍和案例实践的结构。以第3章为例,3.1节和3.2节系统地介绍了Java反射和Kotlin反射的概念和使用方法,是基础知识介绍部分;3.3~3.5节通过案例进一步介绍反射的适用场景,是案例实践部分。
本书的实践案例通常包括案例背景、需求分析和案例实现这几方面。
❑案例背景:介绍案例的需求背景。本书的案例大多源自真实的生产实践,因此案例背景的介绍有非常重要的价值。
❑需求分析:明确需求的细节,拆解需求并转换成技术方案。
❑案例实现:提供详细的问题解决思路以及案例实现步骤。
在系统介绍了常见的Kotlin元编程技术之后,本书还对Jetpack Compose的编译器插件和IntelliJ插件、AtomicFU的字节码JavaScript代码逻辑做了详细的剖析。
与绝大多数技术书类似,本书包含了大量代码。为了提升阅读体验,我在编写本书时对代码做了以下优化:
❑省略不必要的部分,避免代码冗长而浪费篇幅。
❑代码缩进为2个空格,以降低缩进对阅读体验的影响。
❑核心代码注释覆盖率不低于30%,方便读者快速理解代码的含义。
❑核心代码单行长度不超过80个字符,避免排版后出现折行的问题。
❑在部分代码清单的开始处标注其所在的模块、文件或者函数等信息,方便读者自行查找相关源代码。
❑代码字体采用JetBrains Mono,该字体由Kotlin项目团队所属公司JetBrains为开发者专门打造,更适合代码的阅读。
本书阅读对象
本书探讨的内容有一定的复杂度。在阅读本书之前,读者需要对Kotlin语言的语法有较为深入的理解,也需要具备一定的编译原理的基础知识。
本书适用于有一定基础的Kotlin开发者,包括但不限于正在使用和希望使用Kotlin开发Android、Web服务、iOS、前端等应用的开发者。
本书非常适用于希望在Kotlin相关开发领域实现进阶的读者。本书介绍的内容对读者提升自身编程水平以及团队提升研发效率都有非常大的参考价值。
本书不会介绍Kotlin的基础语法,因此建议Kotlin初学者先阅读相关基础书。
如何阅读本书
本书基于Kotlin 1.8.0系统地介绍了Kotlin元编程的基本概念、技术方案、应用场景和实践技巧。
本书主要分为三部分,分别介绍如下。
第一部分为元编程的基础知识(第1章和第2章),为后续的元编程实践提供知识储备。如果读者有一定的Kotlin元编程基础,可以直接阅读第二部分内容。在阅读过程中,如果遇到概念相关的问题,也可以随时翻阅这部分内容。
第二部分为元编程的技术实践(第3~8章),涉及运行时的反射、源代码生成、编译时的符号处理、程序静态分析、编译器插件、元程序的开发和调试等内容。这部分的章节安排相对独立,读者可以根据自己的实际需求选择阅读相应的章节。需要说明的是,DeepCopy项目是贯穿这部分内容的综合案例,在介绍每一种元编程技术方案时,我们都会给出DeepCopy项目中对应的技术方案的实现,希望能够帮助读者加深对不同的元编程技术方案的认识。在了解了元编程的常见技术之后,本书在第8章重点介绍了元编程项目实践中编写单元测试和集成测试的常见方法与技巧,以提升读者开发元编程项目的效率。
第三部分为综合案例(第9章和第10章)。第9章对Jetpack Compose的编译器插件和IntelliJ插件做了详细的剖析,这一章内容实际上是对第7章的延伸。通过阅读这一章,读者可以进一步加深对Jetpack Compose的设计思路的认识,同时也能充分领略编译器插件的魅力。第10章对AtomicFU的编译产物处理进行了详细的剖析,包括对Kotlin JVM的编译产物JVM字节码和Kotlin JS的编译产物JavaScript代码的处理,这一章内容是对Kotlin元编程的拓展和延伸。
本书的约定
本书正文中涉及的外部依赖版本均使用$version来占位,以便我在本书的配套源代码中统一维护。
本书正文中出现的类、函数或者属性,通常采用“类名#函数名”或者“类名#属性名”的书写格式,这种格式可以有效地区分出类名的包名部分,也可以使读者直接在IntelliJ IDEA中通过该格式快速定位到对应的函数或者属性。例如Resolver#getClassDeclaration-ByName(String)是指Resolver类的getClassDeclarationByName函数,参数类型为String。如果函数的参数列表不存在歧义,我也会省略其参数列表,例如DeclarationChecker#check(...)。
本书的代码清单以Kotlin代码为主,涉及其他编程语言的代码清单会在第一行给出标识。例如:
代码清单10-57 移除对value属性的访问之后的结果
本书为部分代码清单提供了位置说明,以便读者查找,例如:
代码清单3-14 公共标准库中KClass的定义
这段代码给出了公共标准库中KClass的定义,它定义在kotlin-stdlib-common模块的KClass.kt文件中。基于这些位置信息,读者可以方便地在Kotlin官方源代码中找到对应的代码来了解更多信息。
为了避免影响阅读体验,本书还对不必要的代码做了省略,例如:
代码清单5-17 获取符号的修饰符
这段代码的目的是介绍如何获取Element的修饰符,因此省略了Element实例的获取过程。
本书在展示编译器错误提示信息时,统一采用了以下格式:
下面是一个具体的例子。
代码清单9-33 f1在内联过程中与DisallowComposableCalls产生冲突
编译器给这段代码中的函数F1的参数部分提供了内容为“Parameter f1 cannot be inlined inside of lambda argument block of F2 without also being annotated with@DisallowComposableCalls”的错误信息,这段错误信息在Kotlin编译器(或者编译器插件)中对应名为“MISSING_DISALLOW_COMPOSABLE_CALLS_ANNOTATION”的错误。
勘误和支持
由于水平有限,编写时间仓促,以及技术不断更新,书中难免会出现一些错误或者不准确的地方,恳请读者批评指正。
读者可以通过以下方式提供反馈:
1)关注微信公众号“霍丙乾bennyhuo”,回复“Kotlin元编程”,在收到的消息页面评论留言。
2)在本书主页https://www.bennyhuo.com/project/kotlin-metaprogramming.html评论留言。
本书主页上提供勘误表,我会在收到反馈后及时将问题整理并补充到勘误表中,对于一些比较重要的问题也会专门通过微信公众号和我的个人网站提供补充材料。
书中的全部源文件可以从https://github.com/bennyhuo/KotlinMetaProgrammingInAction-Sources下载。如果你有更多的宝贵意见,也欢迎发送邮件至bennyhuo@kotliner.cn,期待得到你们的真挚反馈。
致谢
感谢我的家人,是他们一如既往地支持才让我在成长过程中敢于尝试和坚持,也是他们的陪伴才让我有时间和精力去完成这样一本书。
感谢小猿口算团队的同事们。得益于猿辅导公司内部良好的技术氛围,我和团队的同事们有机会在提升研发效率、优化程序架构上深入探索Kotlin的各种元编程能力,这为本书的写作提供了素材。
感谢Kotlin中文社区和Google开发者社区的朋友们,本书的许多内容都曾在社区组织的一次次活动中得以锤炼和提升。
感谢参与审稿的朋友们,他们是李涛、孙国栋、陈轲、孟祥钊、2BAB、程序员江同学、鹿瑞朋、贾彦伟、乔禹昂和叶楠。特别感谢李涛,他也是为《深入理解Kotlin协程》贡献了最多勘误的读者。
谨以此书献给所有Kotlin开发者!
霍丙乾
2023年4月2日
[1]本书已由机械工业出版社出版,ISBN为978-7-111-65591-6。——编辑注