其实早在2017年初就知道Kotlin了,只不过一直没研究过。那个时候Google IO还没开,Kotlin和Android还处于地下恋情阶段。Kotlin的主页上有一行大字:
100% interoperable with Java
然而那并没有什么卵用,没有人会去注意它,毕竟这个世界上的语言多如牛毛。哪怕是写下这篇文章的2018年3月,Kotlin也只能勉强挤进编程语言排行榜的前50。直到2017年的Google IO宣布Android支持Kotlin。
Kotlin的Google Trend突然迎来了火箭般的上升,所有人都在问,Kotlin是个啥?
在Gradle内部,有一个组一直在开发Kotlin DSL,经常有人在Slack群里抱怨写了Kotlin就回不去了。这周末我花了一天时间看了一下Kotlin的文档,也写了一个100% Kotlin的项目练手,详见我的这篇文章JUnit 5 Unroll Extension for Kotlin。
语法奇怪
Kotlin给人的第一印象是语法很奇怪,经常写着写着就不由自主地写成了Java,还不禁纳闷,咋红了呢?对于我这个初学者来说,根本不可能在离线状态下写Kotlin项目——许多问题文档里面找不到,要去Stack Overflow或者Kotlin的论坛里面找。熟悉之后就好多了,不是什么大问题。
写起来爽
抛开语法,Kotlin写起来确实很爽,和IDEA搭配的手感自然是没的说,毕竟是亲儿子。那感觉就像是……想挠痒痒的时候,按下Alt+Enter键,IDEA就把痒痒挠放到了痒的地方,只要再按一下Enter就能挠个痛快。总体上来说,写Kotlin就像是在写Java 8 + Groovy的杂交品种。它是完全静态强类型的,比Groovy不知道高到哪里去了。写多了动态语言的人都知道:
动态语言一时爽,事后debug火葬场
它的闭包系统和Groovy非常像,却又能和Java的Lambda表达式/方法引用无缝衔接,这是我觉得最厉害的。函数式编程和Stream结合在一起,写起来行云流水,很舒服。其实这并不是非Kotlin不可,纯Java也能做到,但Kotlin加了一些新料让这个过程更顺畅。比如说Kotlin的also
:
翻译成Java大概是:
这只是一个例子,Kotlin中有不计其数的语法特性逼迫你用函数式思维思考并编程,这样带来的结果是更加优雅的代码。
至于后来的维护者能不能看懂……随缘吧。
Extension
Groovy的核心是元对象协议(MOP),说白了就是当调用一个对象的方法/属性的时候,Groovy先进行一次运行时查找,找到了,就调用之,否则报错。很明显,这个机制是一柄双刃剑:我们可以动态地往Groovy里面添加方法,却失去了编译检查带来的安全。
而Kotlin是静态的,不可能往里面动态地加东西。老师老师,那我特别想给已经存在的类加一些方法,比如下面这个方法,咋办?
assert(" ".isBlank())
Java的答案是StringUtils.isBlank(String s)
。在Java世界里,随便打开哪个项目,搜索一下,你都能看到几个十几个不等的StringUtils
类。
这么不优雅的写法,你说Kotlin能忍么?它搞出了一个Extension机制。对于上面这个例子,Kotlin的解决方案是:
fun String.isBlank(): Boolean {
...
}
然后就可以直接对字符串对象调用isBlank()
了,就如同这个方法是它自带的一样。
糖特别多
Kotlin的语法糖多到令人发指的地步。总结一下就是,编译器能做的事情绝不让你做。举个例子:
public boolean isEmptyString(Object obj) {
return (obj instanceof String) && ((String)obj).isEmpty();
}
Kotlin说,费那事干啥!&&
后面的那个转型不是脱了裤子放屁么!
public isEmptyString(obj: Any): Boolean {
return (obj is String) && obj.isEmpty() // 在&&后面自动转型为String
}
BTW,对于这种一行的函数,可以简化成:
public isEmptyString(obj: Any): Boolean = (obj is String) && obj.isEmpty()
在各种分支中,只要是编译器能推断出来,所有的转型、空指针检查统统不用你自己做。你如果非要自己做的话,IDEA会提示你,这个地方可以优化哦亲!
上手难度
Kotlin上手还是有一定的门槛的,至少我觉得,以四年前我刚进阿里的时候的代码经验应该驾驭不了,尤其是by
这种高级用法……我觉得这货最适合有几年编程经验的人(无论什么语言)。新人还是老老实实码一段时间的Java比较合适,不要一上来就想搞个大新闻。要排个序的话,
Java > Groovy > Kotlin
什么,你说Scala?我还是讲个故事吧——年前跟LinkedIn的一个小伙聊了两句,因为LinkedIn的主力Web框架是Play,我特好奇,你们是怎么招到写Scala的人的?
对方回答,因为Scala隐藏的坑太多,现在都强制写Java了……
这个故事告诉我们,在每门光鲜亮丽、说的比唱的还好听的JVM语言背后,都有无数不为人知的大坑。如果没有老司机带路的话,玩玩就行,别把自己身家性命压上……可能会翻车的。
Gradle DSL
在JUnit 5 Unroll Extension for Kotlin的开发过程中,我尝试完全用Kotlin DSL配置Gradle,磕磕绊绊总算是成功了,期间请教了隔壁组的Paul好多问题。用Kotlin写Gradle DSL最大的问题其实不在于它的强类型,而在于……几乎所有的第三方插件给出的demo都是Groovy的格式,需要人肉翻译成Kotlin,有的甚至要去翻插件的源代码……
不过有一点可以确定,虽然kotlin DSL还没到1.0
版本,但是生产上使用已经没啥问题了,Gradle项目的构建配置*.gradle
已经全面转向了*.gradle.kts
。
有关Groovy和Kotlin配置Gradle构建的事情,下次专门开一篇帖子讲吧。