gitbook/朱涛 · Kotlin编程第一课/docs/472129.md
2022-09-03 22:05:03 +08:00

150 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 开篇词 | 入门Kotlin有多容易精通Kotlin就有多难
你好我是朱涛欢迎和我一起学习Kotlin。
作为一名Kotlin、Android领域的谷歌开发者专家我曾经负责过陌陌创新业务的Android客户端。从2017年开始我和我的团队成员们就一直在探索Kotlin在Android中的应用并在Kotlin函数式编程、Kotlin DSL、Kotlin协程以及Android Jetpack方面积累了一些实践经验。我的博客“Kotlin Jetpack实战”也影响和帮助了数万名Kotlin、Android开发者。
Kotlin于我来说就如恋人一般令我深深地着迷。在过去的5年里我一直在使用Kotlin进行Android研发的工作。但实际上在使用Kotlin之前我的主力语言是Java那段时间我负责过陌陌Android客户端的代码规范以及性能优化工作。在这段工作里我见过各式各样的**Java烂代码**有些烂代码是程序员主观疏忽写出来的而还有些代码是业务本身复杂度决定的。那个时候我就意识到了Java语言的一些缺陷。
* **语法表现力差。**
比如Java 1.8之前不支持Lambda表达式匿名内部的写法繁琐在函数方面不支持高阶函数不支持参数默认值也不支持函数命名参数。当我们需要在Java当中实现类似需求时不得不自己寻求其他替代方案这就进一步提高了开发难度降低了开发效率。
* **可读性差,难维护。**
如果我们单独去看Java的每个语法表现力的问题可能会觉得没什么大不了。然而当这样的问题积少成多并且随着工程复杂度的提升语法表现力的问题会进一步演变成可读性问题、维护性问题。
举个例子Java当中的Callback如果只是一到两个Callback的嵌套那么它还在容忍的范围内一旦业务变得复杂Callback嵌套超过3层代码可读性就会急剧下降而后的维护工作将会变成一场灾难出现Bug也只是迟早的问题。
* **Java自身的语法设计也使它更容易出错。**
比如Java基础类型的隐式转换你可以直接将字符变量赋值给整型变量而编译器也不会报错。再比如Java的内部类会偷偷持有外部类的引用从而在某些场景中导致内存泄漏。Java这样的语法设计就让我们程序员更容易写出Bug。
* **并发编程在Java当中也是一大难题。**
在Java当中线程与并发以及它复杂的同步机制它们就像是一头头难以驯服的野马初中级Java程序员都会对其望而生畏。
以上Java的所有缺陷最终反映到实际工作中就会变成**前期开发效率低,中期线上问题多,后期代码难维护。**其实归根结底都是因为Java实在是太老了。而Kotlin作为一门刚出生不久的语言就是为了解决这些问题而生的。
在与Kotlin相伴5年的过程中我一直在研究、探索这门语言的原理和使用技巧也沉淀了一些实践经验和思考感悟希望通过这门课能给你带来一些新的有关Kotlin的认知以及使用参考也能够让你在学习之后可以使用Kotlin来解决工作中的实际问题。
## Kotlin为什么值得学
其实不管你之前是不是有过Java的使用经验你都需要来学习一下这门年轻的语言。我认为主要有这样三个原因。
**第一,极高的生产效率**
Kotlin具备简洁的语法和现代化的语法特性让使用者可以用更少的时间以更高的标准来完成更多的工作。换句话说也就是跟Java正好相反前期开发效率更高中期线上问题更少后期代码更容易维护。
以我自身为例在我们团队完全适应了Kotlin的开发节奏以后线上崩溃率就大大降低了而空指针异常也几乎没有了。另外曾经要3人完成的工作在使用Kotlin以后2个人就能完成而且还能完成得更好。
为此不仅各个大厂的Android部门在积极转型就连Android官方团队也都在用Kotlin写底层的源码Kotlin相关的SDK也层出不穷。到目前为止各个大厂的Android招聘要求里都会加上一条“要求熟悉Kotlin”或“熟悉Kotlin语言者优先”。
**第二,强大的兼容性**
Kotlin可以与Java混合编程这一点尤为重要不然Kotlin的吸引力将大打折扣。因为在我们的实际工作当中大部分情况都是在老旧工程的基础上去开发新功能的而将整个模块甚至是程序推倒然后用Kotlin重写其实是很不现实的。
Kotlin强大的兼容性就让我们可以复用从前的Java代码也能让我们以渐进的方式从Java迁移到Kotlin而不必担心是不是要一次性重写很多代码从而产生新的问题。
**第三科技巨头加持Kotlin的发展前景很广阔**
2017年Google宣布Kotlin成为Android的官方语言后人们对于Kotlin的关注度就一直在上升。而这也就导致很多人听到Kotlin都会下意识地认为它是用来写Android的。
其实Kotlin不仅仅只是在Android领域有所建树据我所知[Amazon](https://talkingkotlin.com/qldb)、[Adobe](https://medium.com/adobetech/streamlining-server-side-app-development-with-kotlin-be8cf9d8b61a)都有将Kotlin应用到后端开发至于Kotlin跨平台方面国际上[Philips](https://kotlinlang.org/lp/mobile/case-studies/philips)、[Square](https://kotlinlang.org/lp/mobile/case-studies/cash-app)等公司也都有不错的实践国内的携程技术团队在这方面也有不少探索和实践。随着2021年Android Jetpack Compose的发布JetBrains在其基础上又扩展出了[Compose-jb](https://github.com/JetBrains/compose-jb)让Kotlin还能跨平台编写UI界面。
总而言之对于Android开发者来说Kotlin已是**必学**的编程语言而对于其他领域的开发者来说Kotlin也有着非常好的前景现在入坑还来得及
## Kotlin到底难在哪
那么在看到了Kotlin有如此多的使用优势和如此广阔的发展前景之后也有不少人都纷纷投入了Kotlin的学习大军当中甚至很多人都是在有了Java的知识基础和使用经验之后再去学习的Kotlin而且他们会觉得Kotlin的学习很简单它跟Java的很多语法都是一样的没啥难的嘛。
但其实这是对Kotlin的一种误解。**带着Java经验学习Kotlin这既是一种助力同时也是一种阻碍。**在Kotlin学习的前期Java经验可以帮我们快速掌握它的语法但到了后期我们脑子里的Java老一套会限制我们进一步提升。如果我们迟迟不转变自己的思维只会在Kotlin学习之路上越跑越偏。
从我的实践经验来看Java开发者学习Kotlin的难点主要在于**思维的转变**
* **不变性思维**虽然Java当中也存在final不变性然而Kotlin却将这件事做到了极致Kotlin要求我们在定义一个变量、集合的时候就明确规定它的不变性。Kotlin这样的设计就是希望在软件当中尽可能地消灭可变性。如果我们脑子里没有不变性思维我们写出来的Kotlin代码将“惨不忍睹”。
* **空安全思维**Kotlin的类型系统分为可空和不可空类型这样的设计也彻底改变了我们的编程习惯。想要处理好Kotlin的空安全问题我们也必须完成思维的转变。
* **表达式思维**在Kotlin当中if、else、when之类的语句还能作为表达式来使用这样的语法特性往往可以帮我们简化代码逻辑。
* **函数思维**在Kotlin当中函数是一等公民。Kotlin也是一门积极拥抱函数式编程的语言在Kotlin的一些语法设计上总能看到一些函数式的影子。命令式编程与函数式编程它们两者有各自的优缺点也有各自擅长的领域。而Kotlin除了有命令式的一面对应地它还有函数式的一面。
* **协程思维**Java开发者在学习Kotlin协程的时候尤为痛苦因为在Java开发者脑子里只有“线程思维”而对协程一无所知。想要真正地理解和掌握Kotlin的协程我们需要从根本上改变我们脑子里的思维模型。
Java开发者学习Kotlin很难那么零基础学习Kotlin会不会更简单呢毕竟不存在旧思维束缚啊
其实不然零基础也就意味着编程经验的欠缺。因此零基础学习Kotlin最大的问题在于**容易浮于Kotlin语法表面体会不到Kotlin设计的美感悟不出Kotlin特性的应用场景看不到Kotlin底层的实现原理。**
不过,请放心,以上所有的问题,在这门课当中,都会得到解决。
除了以上的学习难点以外Kotlin本身的学习曲线和其他的语言不太一样它是一门**易学难精**的语言。Kotlin的语法非常简洁确实极其容易入门但同时它又拥有许多的新特性不容易掌握。**即使你掌握了Kotlin的一个个语法想要写出优雅的Kotlin代码仍然不是一件容易的事情。**
我凭啥这么说呢让我从自己学习Kotlin的经历说起。
![图片](https://static001.geekbang.org/resource/image/2e/d0/2ea3975d4dccc3dbab871d50eab171d0.jpg?wh=1920x1013)
从我的亲身经历来看我的Kotlin学习之路大致分为三个阶段
* **第一阶段,初窥门径。**
由于Kotlin的语法非常简单刚开始我非常自信在学完基础语法以后就开始试着以Java的思维写Kotlin代码而Kotlin独有的特性我却很少用到。渐渐地我发现了不对劲的地方因为我**并没有发挥出Kotlin的简洁与高效的优势**。同时我内心的自信也逐渐变成了迷茫。我终于知道自己对Kotlin的理解还非常得浅显。
* **第二阶段,登堂入室。**
这时候难度就上来了我开始钻研Kotlin的一些新特性的原理并且研究它们的使用场景。在这个过程中随着我对Kotlin的理解的深入我也真切地感受到了Kotlin语法的美感同时也深深地爱上了Kotlin这门语言。这时候我终于登堂入室了。
* **第三阶段,豁然开朗。**
当我觉得自己对Kotlin已经足够了解的时候我决定学习Kotlin的协程。这时候我几乎绝望了。面对一堆全新的概念我几乎毫无头绪协程、作用域、上下文、launch、async、Channel、Flow、异常处理我完全不知该如何入手。我一边研究协程源码、一边在工作中实践这一路我踩过不少坑也引发过线上故障磕磕碰碰之间忽然有一天量变产生了质变我终于感觉豁然开朗前方一片坦途。
现在回过头来看当初我的Kotlin学习之路是**艰难且曲折**的。主要还是因为那时候优质的Kotlin学习资源不多且不成体系。大家都是跟着官方文档自学而Kotlin官方文档对初学者又不那么友好因此只能“摸着石头过河”。
由于我曲折的Kotlin学习经历这也决定了我们这门课会力求**简单易懂**。比如为了让你理解Kotlin的扩展函数的使用场景我精心制作了普通函数与扩展函数的转换动画
![图片](https://static001.geekbang.org/resource/image/ee/43/ee2570eb0a1b10155ecf34bd7f291343.gif?wh=720x405)
另外,**协程一直都是Kotlin学习的难点。**在过去这几年的研究中,我总结出了一套“**协程思维模型**”。在我写协程代码的时候,我的大脑里会有一套对应的模型,来帮我模拟协程的运行过程。而这些,我也会在这门课中,以最直观的方式传授给你。
比如,下面这张图就展示了协程、线程与进程之间的关系。它能帮你在大脑里建立一个清晰、具体的协程模型。
![图片](https://static001.geekbang.org/resource/image/31/9d/31f035dc1b008be1912b3e221e505f9d.gif?wh=720x405)
再比如说,为了让你看到协程代码背后**挂起与恢复**的细节,我精心制作了这个示意图。它可以让你对协程挂起函数有一个更深入的认识。
![图片](https://static001.geekbang.org/resource/image/6b/2b/6b772a6ef97e6b5587690d10a8f5bb2b.gif?wh=720x405)
当然,动画解析只是一种讲述方式,我选这种方式,只是因为它最直观。咱们这门课程的核心理念还是:**帮你快速掌握Kotlin的核心知识点理解Kotlin的编程思想最终可以用漂亮的Kotlin代码来解决工作中的问题。**
## 怎么学习Kotlin
Kotlin当中涵盖了很多新的语言特性要学会这些新特性的语法其实很简单但是要理解Kotlin设计这些新特性背后的意图却不容易。而这恰好就是我们需要重点关注的地方。因为只有当我们知道Kotlin为什么要设计这些新特性我们才能弄清楚这些特性的最佳使用场景。
![图片](https://static001.geekbang.org/resource/image/f6/9d/f65548f66702b86a7aa4433aeeea319d.jpg?wh=1920x1315)
所以在课程中我会尽量去揣测Kotlin设计者的思路去对比Kotlin和Java语法的差异然后用一些实际案例来给你讲解Kotlin新特性的使用场景。具体来看这个课程主要分为四个部分。
* **基础篇**
这个模块我们会集中精力攻克Kotlin的核心语法包括基础语法、面向对象、高阶函数、扩展、委托、泛型、注解和反射。并且每学习三到四个语法我们就会通过一个**实战项目**将这些知识点串联起来,从而达到学以致用的目的。
* **协程篇**
协程是Kotlin当中极其重要的特性同时它也是Kotlin当中极其难学的特性。在这个模块我会深入讲解协程当中的各个概念并且会给你介绍协程的思维模型**帮助****你****完成“线程思维”到“协程思维”的转换**。当然了,在这个过程中,我也会结合实战项目,让你能上手体验协程的魅力。
* **源码篇**
在理解了前两个模块的内容之后你就算是初步掌握Kotlin这门语言了。不过我们不仅**要知其然,还要知其所以然**。
Kotlin官方的源代码其实是一座宝库里面充满了Kotlin的最佳实践。通过研究Kotlin的源代码我们可以进一步加深对Kotlin理解同时也可以去探究它底层的原理。比如Kotlin协程的挂起函数到底是如何挂起的Kotlin协程到底是如何与线程衔接的这些问题我都会在这个模块用尽量简单的方式解释给你听。
* **Android项目篇**
目前来说Kotlin最主要的应用还是在Android领域。因此在学完前面几个模块以后我们再来看看Kotlin在Android领域到底能做什么。Kotlin凭什么能被Google指定为“官方语言”如何使用Kotlin来提升开发效率如何将Kotlin的特性融入到Android的架构设计中最后我也会带你一起来**用Kotlin写一个简单的Android App**。
除此之外,我还会不定期进行**加餐**给你分享Kotlin在各个领域的一些知识来进一步扩展你的Kotlin知识面。比如Kotlin协程在后端、Android端的应用Kotlin Multiplatform在跨平台当中的应用以及Compose在UI领域的应用。
![](https://static001.geekbang.org/resource/image/1a/eb/1a1a47b704fc22ec6646b43b8fd7a4eb.jpg?wh=1564x8151)
从课程安排上,相信你已经明白了:这是一个理论与实战结合的课程。因此,在学习的过程中,我希望你能够一边学习,一边跟着我完成课程配套的实战项目。另外,如果你在学习的过程中有了一些新的感悟,也欢迎你将其以博客、部落、留言评论等形式发表出来,分享给更多的人。还有一点是:如果你有不懂的地方,一定要在评论区讲出来,我们一起交流。
你可以自己立个Flag每节课都在评论区分享思考题的思路。我相信几个月后你一定会有巨大的提升。
最后希望你也可以和我一样爱上Kotlin。