03 | Kotlin原理:编译器在幕后干了哪些“好事”?
朱涛
你好,我是朱涛。
在前面两节课里,我们学了不少 Kotlin 的语法,其中有些语法是和 Java 类似的,比如数字类型、字符串;也有些语法是 Kotlin 所独有的,比如数据类、密封类。另外,我们还知道 Kotlin 和 Java 完全兼容,它们可以同时出现在一个代码工程当中,并且可以互相调用。
但是,这样就会引出一个问题:Java 是如何识别 Kotlin 的独有语法的呢?比如,Java 如何能够认识 Kotlin 里的“数据类”?
这就要从整个 Kotlin 的实现机制说起了。
所以,今天这节课,我会从 Kotlin 的编译流程出发,来带你探索这门语言的底层原理。在这个过程中,你会真正地理解,Kotlin 是如何在实现灵活、简洁的语法的同时,还做到了兼容 Java 语言的。并且你在日后的学习和工作中,也可以根据今天所学的内容,来快速理解 Kotlin 的其他新特性。
Kotlin 的编译流程
在介绍 Kotlin 的原理细节之前,我们先从宏观上看看它是如何运行在电脑上的,这其实就涉及到它的编译流程。
那么首先,你需要知道一件事情:你写出的 Kotlin 代码,电脑是无法直接理解的。即使是最简单的println("Hello world."),你将这行代码告诉电脑,它也是无法直接运行的。这是因为,Kotlin 的语法是基于人类语言设计的,电脑没有人的思维,它只能理解二进制的 0 和 1,不能理解 println 到底是什么东西。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
Kotlin编译器的幕后“好事”:深入探索Kotlin编译器的工作原理,揭示了Kotlin代码经过编译后会变成Java字节码,实现了Kotlin和Java的兼容。文章介绍了两种研究Kotlin原理的思路,并通过具体操作步骤,帮助读者快速了解Kotlin的实现细节。通过分析Kotlin的Long类型和接口语法的局限性,揭示了Kotlin编译器在背后进行的翻译工作,将Kotlin代码翻译成Java能理解的格式。文章还总结了Kotlin编译器在幕后所做的“好事”,如类型推导、原始类型转换、字符串模板处理等,使得读者能够深入了解Kotlin编译器的工作原理,为进一步学习和研究Kotlin打下基础。整体而言,本文通过简洁清晰的语言和实际例子,让读者能够快速了解Kotlin编译器的工作原理,体现了文章的技术特点。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《朱涛 · Kotlin 编程第一课》,新⼈⾸单¥59
《朱涛 · Kotlin 编程第一课》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(32)
- 最新
- 精选
- Renext思考题: 转换成 java代码就一清二楚,两种方式的isAdult本质不是同一个东西: 1-通过自定义 getter 来实现的方式,isAdult其实是一个方法。外部每一次调用,都是拿最新的age进行计算,所以age的值有变动,isAdult()的结果是最新的。 2- val isAdult = age >= 18 这种方式,isAdault是一个final变量,只会在对象新建时,在构造方法中,根据age的值赋值一次。所以,之后age的值如果有变动,isAdault值是永远不变的。
作者回复: 赞!
2021-12-31361 - PoPlus思考题: 如果采用 val isAdult = age >= 18 这种写法,那么错误会表现在给某个 Person 对象的 age 属性二次赋值时,isAdult 属性仍会是一个旧的 Boolean 值。原因:从反编译出的 Java 代码可以看出,isAdult 属性会被转换成一个 final 修饰的 Java 属性且在构造方法里赋好值了,那么意味着即使 age 属性后期修改一万遍,isAdult 属性也只会是它原来的那个初始值。 而如果用 getter 的方式则不会有这个问题,因为 getter 方式会把 isAdult 属性转换成 getter 方法而不是 final 修饰的属性,每一次调用,isAdult 属性就会动态的根据 age 属性来判断返回值。
作者回复: 赞!分析的很到位。
2021-12-3112 - 阶前听雨太赞了,看了很多书和博客,基本都在讲kotlin多好用。从根本上讲kotlin的还是这门课,很多以前懵懵懂懂的概念都豁然开朗,太赞了。
作者回复: 你的鼓励就是我的动力。我们一起加油!
2021-12-3110 - 逢庆1. val isAdult get() = age >= 18 反编译后可以看到,会生成方法: public final boolean isAdult() { return this.age >= 18; } 2. val isAdult = age >= 18 反编译后,可以看到: 会定义一个isAdult属性: private final boolean isAdult; 并在构造函数里根据age来赋值: this.isAdult = this.age >= 18;
作者回复: 没错。
2021-12-317 - 3.141516kotlin 的一些语法特性在编译为字节码后会增多 class 数量,所以会增加字节码的大小。 想请教下老师,在 Android 中,Kotlin 还有哪些方面会增加包大小呢?谢谢
作者回复: 其实,我们一般说Kotlin增大包体积,主要只两个方面: 1. Kotlin标准库+反射库+协程库 2. 字节码增加class数量
2022-02-095 - 文茂权JVM 由于存在多种实现,依赖的是一套标准规范。尽管学习 Kotlin 不需要直接接触 JVM ,但参考 JVM 的设计规范对于我们学习 JVM 编程语言的设计是很有作用的。 这里附上 JVM 不同版本的设计规范文档:https://docs.oracle.com/javase/specs/index.html
作者回复: 赞!感谢补充。
2022-01-165 - droidYuKotlin语言的简洁得益于Kotlin编译器的强大,之所以Java和Kotlin能完全兼容,是因为Java和Kotlin编译后的成果都是Java字节码。
作者回复: 是的。
2022-03-204 - 郑峰You can define custom accessors for a property. If you define a custom getter, it will be called every time you access the property (this way you can implement a computed property). If you define a custom setter, it will be called every time you assign a value to the property, except its initialization.
作者回复: 嗯,是的。
2022-01-153 - qinsi直觉上反编译都是有损的,不知道有没有遇到过反编译结果不对的例子?
作者回复: 确实,字节码才是最接近本质的。反编译成Java之后确实会损失少量信息,但一般都不会有很大的偏差。
2022-01-0122 - PoPlus关于 Kotlin 包装类型优化原始类型,我的实验结果和老师的结论有一点出入,不知道是不是编译器版本的原因。🌚 var a: Long = 1 // private static long a = 1L; val b: Long = 2 // private static final long b = 2L; var c: Long? = 3 // private static Long c = 3L; 未优化成原始类型 val d: Long? = 4 // private static final Long d = 4L; 未优化成原始类型
作者回复: 嗯,这是有可能的,我用的最新版IntelliJ,Kotlin1.6版本。
2021-12-3122
收起评论