Kotlin从2011诞生至今,不过11年而已,但是Kotlin已然成为了新时代编程语言的“当红炸子鸡”,讲述 Kotlin 的教程和文章不胜枚举。所以希望能从一个不常见的视角来带大家了解一下Kotlin,我们拔高维度,先忽略那些繁杂的语法与原理,回顾Kotlin这个语言的发展理念和设计理念,聊一聊Kotlin诞生前后的波谲云滚的历史背景,从而让大家对Kotlin 有所宏观的理解,发掘Kotlin成功的关键所在。
Kotlin帝国的诞生
尾大不掉的java语言帝国
从 java语言被一群嵌入式设备的开发工程师,因为 c&c++ 代码移植搞得苦不堪言而创建出来,已然30个年头了。在其至今依然十分优秀的“跨平台”特性的支持下攻城略地,已然在客户端&后端领域建立起了高高的城墙和宽阔的护城河。但一个组织随着规模的扩大,不可避免由于很多历史因素和内部因素而拖累其发展的节奏。下面我就列举几个java经常为人诟病的问题
不断的冲突与矛盾
早期Java母公司对于Java控制的过于严格。早在伞公司时期,伞公司和微软就因Java的在Windows的实现上起过冲突间接导致了.net c#的出现。Oracle也和Google关于java有过长达10年的诉讼,从而促成了Kotlin成为了Android 的开发言语言。这些争议本质是是大厂之间对于java发现规划的权的一种博弈,这种博弈是客观存在的,但是java的Owner公司,显然没有足够的智慧和机制来平衡各方诉求,从而矛盾升级为旷日持久的诉讼。
迭代缓慢&远离普通开发者
这里的和核心问题在 JCP(Java Community Process)这个组织,JCP这个组织建立之初就是希望以社区的形式促进java的迭代发展。JCP 最核心的制度就是,由成员发起一个JSR(Java Specification Request),之后经过重重审核之后,才会进入java标准库中。而JCP的成员通常由各个企业的相关人员构成。JCP的核心人员都是选举产生,整个JCP像极了古罗马的元老会。个人开发者的话语权比较小。JCP本身也缺少透明度,喜欢各种闭门会议。虽然目前JCP已经在积极的推动自身的改革,但是之前存在的问题依然遗留不少。
稳定与创新
稳定与创新天然就是矛盾的两个方向,显然,对于java来说,稳定是自己的立身之本。保持稳定,逐步迭代是目前的最佳策略。因此各种新时代的语言特性就不太可能加入java标准,从而普及了。
藩镇割据——那些年支持JVM的语言
既然java存在的一些问题,JCP并不打算填补,新王的诞生则是必然,需求总是需要被填补的。因此基于Jvm的各种改进型语言诞生了。我们可以对比一下这些语言
| 目标 | 支持特性 | 现状 | 时间 |
kotlin | 更好的java,替代java | …… | Android开发 | 2011 |
groovy | 支持DSL,成为一个JVM下的脚本语言 | 更强大的闭包 各种脚本特性,怎么写都对…… | Gradle 脚本 grails 后端 | 2003 |
clojure | 新世纪的 Lisp 方言 | 代码即数据,数据即代码 | 少量后端 | 2007 |
Scala | 更好的语言,融合OO与FP,打造大而全的最强JVM语言 | case class pattern matching 多继承,trait,mixin Implicit Feature | spark hadoop | 2001 |
新王加冕
有需求就会有机会,显然Kotlin抓住了这个机会。仔细思考发现,Java原本早的优势“跨平台”的特性依然是一个巨大优势,另外全球也有基数很大的Java Developer。基于Java,并做好与java的兼容,扩展一些新的特性是一个非常务实的选择。
演进原则
-
一直保持语言的现代性。
-
与用户保持持续的反馈循环。
-
使版本更新对用户来说是舒适的。
显然吸纳普通开发者的意见,并且能快速迭代是Kotlin能够迅速崛起的重要原因之一,下面是Kotlin 10周年时对开发者的一段采访,我们可以得知,经过5年的开发,其实Kotlin的稳定版已经和最初完全不同了。而这些不同正是基于一线开发者的反馈而来,是最为贴合普通开发者需求的。这种敏捷的语言开发模式与JCP形成了强烈的反差。这次Kotlin站在了普通开发者一侧,和普通开发者一起用务实的态度,打响了推翻被JCP“元老院”把控的java预言帝国的第一枪!!
2016 年曝光的稳定语言与 2011 年提出的最初想法大不相同。这是 Kotlin 成功的第一个组成部分——Kotlin 是务实的。它不是一种基于一小部分设计者的理论、哲学或假设的语言,而是一种基于实际使用数据的语言,旨在简化从事大型项目的专业开发人员的日常工作。
实用主义
Kotlin 常常被认为是一门近似于 Scala 的语言。不可否认的是,Kotlin 确实从 Scala 身上借鉴了许多。然而,Kotlin 与 Scala 的设计哲学又十分不同。Kotlin 并没有像 Scala 那样热衷于编程语言本身的研究和探索。相反,它在扩展 Java 的同时,又在语言特性的选择上表现得相当克制。Kotlin 在尝试寻找新特性 和 java旧习惯之间的一个平衡性,比如scala 中的 Implicit,强大但是不符合java开发者的认知,Kotlin就不会引入。以此降低Java开发人员的迁移成本。
在语言特性的选择方面,相较于 Scala,Kotlin 更加立足现实,它现阶段仍没有宏,也拒绝了很多所谓的高级函数式语言特性。但它在 Java 的基础上发展出很多改善生产力的语言特性,而且它似乎偏好语法糖,这可以让编程人员的工程开发变得更加容易,自然也更容易受到一线开发人员的喜爱。
Kotlin也非常清楚自己的基本盘是Android,快速的提供了android-ktx 扩展包来提升Android开发者的开发效率。也是Kotlin语言开发者实用主义灵活的体现。
Just Better Java
Kotlin的自我定位非常的清晰。立足于Java,并且利用自己贴近使用者和更新效率高的优势,来获取Java开发人员的青睐。因此早期Kotlin很重要的特性都是在直接解决Java开发者的痛点。比如空安全问题,代码啰嗦问题。比如Kotlin在Java8还没有完全普及的时候,就提供了Java8很多语法特性的Kotlin版本支持。同时保持了与Java之间的无缝互相调用。试问,谁能拒绝这样一个又快又好的“java新版本”呢?
“裙带关系”
Kotlin由JetBrains负责维护,JetBrains也是我们熟悉的Intellij系列IDE的开发者。自然Intellij对于Kotlin的支持程度也是远高于其他语言,比如Kotlin的Intellij插件,Kotlin的代码补全,提示,工具都与Java语言一致,甚至更好……
此外Google对Kotlin的支持也是Kotlin获得目前成就的重要原因,2017 Google宣布Kotlin为Android的推荐语言后,花了大量的资源去宣传和推荐Kotlin。56%的人使用Kotlin作为主要语言进行开发。Google的对Kotlin的支持也是与Oracle公司诉讼最激烈的时候,诉求也很明确。
Kotlin的设计理念
基本理念
https://www.youtube.com/watch?v=PsaFVLr8t4E
可读性>简洁性
复用>表达力
互动性>起源
安全+工具>健全
总结下来Kotlin的设计思想是更加偏务实+工程的。这种设计思想也深入到了Kotlin的各种特性当中。
可读性
很多时候简洁性和可读性是正相关关系,比如
Java
Person person;
for(int i =0;i}
Kotlin
val person = personList.find { it.id == somePersonId }
但是也有负相关的例子。Kotlin放弃可读性性差的语法糖,转而用更多的代码来来补充足够的甚至是冗余的信息来使得代码可读。下面举个对比的例子。
Kotlin
for(a in 1..3){for(b in nums){if(b <2){println( "Value of a: " &#43; a );println( "Value of b: " &#43; b ); }}
}
Scala
for(a <- 1 to 3; b <- numsif b <2){println( "Value of a: " &#43; a );println( "Value of b: " &#43; b );}
复用性
Kotlin的复用性体现在各种扩展函数&#43;标准库函数
如关于集合的相关操作findfilter&#xff0c;IO操作的 use&#xff0c;read等等……这里就不一一枚举了&#xff0c;平常使用的同学一定有深刻的感受,可以大量的减少样板代码。
抄抄抄&#43;融合
上面的理念中提到了&#xff0c;Kotlin语言的开发者不是很在乎&#xff0c;某些特性是否原创&#xff0c;只要是好用的&#xff0c;适合Kotlin&#xff0c;都可以借鉴过来。他们的确也是这么做的。
Kotlin中的 构造函数&#xff0c;Object&#xff0c;SealClass 都借鉴了Scala中的特性&#xff1b;扩展函数参考了Swift&#xff1b;协程参考了 Scala的 Actors&#xff1b;Kotlin的 DSL 参考了Groovy&#xff1b;Kotlin的Unit 和 Nothing 也源自于Scala……
语言特性
空与不空
Null
引用的发明者 Tony Hoare 曾在 2009 年作出道歉声明&#xff0c;声明中表示&#xff0c;到目前为止&#xff0c;空指针异常大约给企业已造成数十亿美元的损失。
在java里面处理方式&#xff0c;是引用google的optional以及Lombok库的注解来避免空指针。但是不得不说&#xff0c;optional被滥用的代码比比皆是&#xff0c;lombok被滥用也会给代码的可维护性增添了不消负担 。
而Kotlin的方案是把 nullability 的支持&#xff0c;放在了语言的类型设计之中。本质上是将“空”这一个问题&#xff0c;转移到编译时及时发现和解决。这种思路也是目前比较流行的空安全解决方案。如&#xff1a;Dart&#xff0c;Swift都采用了这种方式。
其他类型系统
基础类型
Kotlin的基础数据类型 &#61;&#61; java的基本类型&#xff0c;从而减少了封箱和拆箱的过程。是个很好地设计
Unit vs void
函数都是需要一个返回值的&#xff0c;这也算没有返回值的函数的副产物了。java中的处理是直接执行return 字节码。而Kotlin调整为返回Unit的差异在于Kotlin中可以接收 这个返回值了 ,是一种更加整齐的设计&#xff0c;并且Unit在高阶函数中也有明确的含义
fun aaa(){}fun bb(){val a&#61; aaa()
}
Noting
Noting的出现是为了补全不可达语义下的函数返回值&#xff0c;来帮助严谨语义&#xff0c;增强可读性的
场景&#xff1a;
fun exitProcess():Nothingfun aa()
{val r &#61; if(xxx){throw Exception()} else {return 0}
}
可变与不可变
区分可变与不可变是现代很多语言的非常好的一个特性&#xff0c;能够避免很多复杂的问题。对于任何程序&#xff0c;在读代码分析代码意图的时候&#xff0c;不可变意味着只要我跳转到定义我就可以知道它的值是怎么来的&#xff0c;这方面的逻辑就很清楚。如果是可变的变量&#xff0c;它的值是什么&#xff0c;取决于最后一次写操作。比如一个变量出现了10次&#xff0c;如果是可变变量&#xff0c;你想分析它的值的情况&#xff0c;你需要肉眼遍历变量的10次引用&#xff0c;然后找到最近一次的写操作。
不可变类可以在多线程环境下更容易判断值的情况。我们发现Kotlin 读取可空的、可变的成员变量&#xff0c;即使是上下两行判空也是不行的&#xff0c;就是考虑多线程问题
此外函数编程也是要求参数尽可能是不可变的
class A{private var value:String? &#61; nullfun b(notNullString:String){ …… }fun a(){if(value !&#61; null){//报错b(value)}}
}
因此在Kotlin中有很多可变和不可变的限制
-
val 与 var
-
集合类区分可变与不可变
-
参数不可变
组合与继承
组合优于继承已然成为近些年面向对象编程圈的一个共识了&#xff0c;这种编程思维其实和语言无关&#xff0c;但是Kotlin提供了很多方便的语法特性帮助我们来高效的实现组合。
另外Kotlin也多少透漏出一些倾向&#xff0c;希望开发者注意继承的使用&#xff0c;类和方法默认都是final的&#xff0c;需要增加open才能被继承
open class A{open fun a(){}
}
总结
Kotlin是由很多原因综合成就的&#xff0c;对我而言&#xff0c;最能吸取经验是的是其务实的精神&#xff0c;和敏捷语言开发方式和理念。
曾经有一位技术人员公开怒怼乔布斯不懂技术&#xff0c;乔布斯是这样回应的
我经常发现&#xff0c;你得从用户体验出发&#xff0c;倒推用什么技术&#xff0c;你不能从技术出发&#xff0c;然后去想如何才能卖出去。在座的没有人比我犯过更多这样的错误&#xff0c;我也搞到伤痕累累&#xff0c;我知道这就是原因&#xff0c;当我们尝试去为苹果思考战略和愿景&#xff0c;都是从能为用户带来什么巨大利益出发&#xff0c;我们可以给用户带来什么&#xff0c;而不是先找一群工程师&#xff0c;大家坐下来&#xff0c;看看我们有什么吊炸天的技术&#xff0c;然后怎么把它卖出去。
和用户站在一起&#xff0c;才能让你做的事情更加的伟大&#xff01;
转自&#xff1a;Docs