kotlin的一些特性介绍和与java C#的简单对比

前言

这是我之前在知乎上的一些回答的汇总,感觉还是博客园写这些东西方便一点,也算是理下我的一些思路,现将文章整理后,发布在园子里。

为何是kotlin:

很多人对kt没有一个正确的定位,可能大家第一反应是拿它去和scala,groovy比较.
从语法的角度而言,kotlin丰富且严谨到恰到好处的语法糖,表达能力强但不啰嗦,极少的代码冗余。
但老实讲能做到这些的语言也不算少,单看语法,事实上kt比scala还是要略差一筹的,
他们都是非常优秀的jvm语言,总体来说是难分伯仲,kt也没办法将他们甩出一个身位.
但我必须得说,绝大部分情况下(指常规开发),如果你选择kt作为你的第二jvm语言,比用scala,groovy等,
开发工程中的收益要多的多的多...成本亦低的多的多的多(注意我不是单单在说语言层面了)

首先,最重要也是让kotlin与其他jvm语言有本质不同的地方在于:无缝和java程序的衔接以及极低的交互成本。

  1. 老项目想尝新?在maven或gradle里面加个配置,就能开写kotlin了.
  2. 不敢直接用?先用来写UT啊,UT写顺了,你自然会忍不住想继续写。
  3. 已有java代码怎么办?直接用啊,封装都不用,两者可以直接调用,智能提示也都在,反过来kotlin写的库java同样能用。

kotlin的一些典型特征:

静态强类型

这个不多说,java,C#,kotlin都是典型,稍微上点规模的项目,都应该用静态强类型来打底子。TypeScript越来越火也可见一般。
当然我不是说静态就优于动态,这是看场景的,比如需求相对复杂和稳定的后端和随业务迅速迭代的前端,他们的技术诉求肯定就不一样。
比如做gateway,我就觉得动态类型的语言更适合,参考阿里的node.js使用场景。

学习成本

其实大家回忆下学习语言的过程,是花在语法上的时间多,还是花在熟悉标准库上的时间多?
而kotlin则完全没有后者的成本,time还是用的joda,http还是Apache的HttpClient,或者OkHTTP,
也会纠结netty,tomcat,akka 的方案选型,同样需要注意集合类的时间复杂度和线程安全情况。
可以说在熟悉java生态的前提下学习kt,成本是非常低的。

其实我给人安利时候,一般给C#的人说Kotlin,就是“jvm届的C#”
给Java的人说:“你别把它当新语言,你就把他当Java9”,当然9现在已经发布了,我可以换成10了,哈哈。

学习新语言总是会给人带来一些压力,但也要注意语言和语言之间的学习成本的不同,
我曾开玩笑说:我学习scala(入门)花的功夫,足够我学会js,php,python这三门语言了。
而kt的低成本高收益,才是我对它如此推崇的最大原因。

生态支持

最后,也是最重要的优势:jetBrains爸爸全方位无死角超贴心的配套支持
(画外音:用过Resharper,IDEA,WebStorm,PyChrome的朋友,让我看到你们的双手!!)
熟悉jetBrain的朋友,应该能够感觉到,这是一家非常有特色和魅力的公司,其在ide和pl工程领域的积累,大家应该也心里有数.
j系ide都有一个特点,就是对开发者极其友好,
基于语法(AST?)而非文本的代码分析,带来的超高的智能提示准确率和极度便利的重构,
对可能的异常代码的警告和解决方案的提示.jetBrains总是倾向于让开发者写出严谨又简洁且鲁棒的代码。
幸运的是,kt也继承了爸爸的这些特质,不仅仅是语法的严谨,还体现在了开发过程中。
比如maven配置,java交互,nullable的注解提示,idea配套插件.
而且kt是他们内部很早就立项的语言,他家的各路ide都是用kt写的。
各种插件个ide的支持,基本可以和语言版本同步迭代。

说了这么多文字,且废话占多数,想必大家也有点烦了,那我下面就以java和kt的比较为切入点,介绍一些kt的特点吧。
其实就是过一遍 Kotlin/kotlin-koans,建议有兴趣的可以clone个玩玩。

val 定义的变量不可变

var 同C#,val和var都是隐式强类型推断,
val的作用在于,我前面定义一个orderState,即表示,这个变量就只做取值用途,你别再拿来干别的事情了,避免了一值多用的bad small.

默认参数,及参数名传参:

减少无意义多态的使用,但又比js的一值多用直观的多.

labmda写法改进

必须在一个花括号中,如果以lambda为参数,可省略(),看起来很舒服
如果只有一个参数,则可以省略声明,用it代替,(同scala的 _ )
scala的一个参数对应的_只能出现一次,第二个_代表第二个参数,更简洁的写法但带来更模糊的语义,孰优孰劣不谈,但两者的风格差异在这个细节中可见一斑.

nullable

kt对null pointer 问题非常敏感,任何可能的npr都需要显示的处理,如果不处理,nullable会一直往后传染并给出一个警告,
这时候你要么用!!表示我tm确定这里肯定不为null,要么用?:表示如果为空,则表达式的值为后面提供的缺省值. 这个设计基本和C#那边的一样

tems是订单详情的集合,详情包含ActualWeight,但未发生实提则为null,如果是传统写法,需要先判断find出来的是否是null,再判断这个find是否有实提,如果有则返回实提,没有则返回double 0(lambda可省略return)
大家可以体会下这省了多少工夫?

扩展方法,
这是我觉得所有静态语言都应该提供的特性,原理非常简单,但带来的写法上的优化非常有价值
kt和C#扩展方法原理大致类似,就是this作为第一个参数传给静态方法的一个语法糖,但kt不要求强制定义在一个静态方法中

表示所有的string实例,在lastChar的可访问范围内,都多了一个成员函数,其实就是
static StringHelper.lastChar(str:String)
的变种,在不支持em的java看来,就长刚才这个样子,用起来就是如下形式:
H3.em3(H2.em2(Helper1.em1(what)))
low爆了是吧? 下面是我封装的一个操作poi的代码

next是移动到下一单元格,设置样式是复制第一行的样式,其实还可以封装,为了显示表达出我的操作意图,这里就留着了.

说到这里就差不多了,再说也就是抄袭koans,也没啥大的意思了,最后扯点其他的作收尾吧.

谈一谈我对语法糖的看法:

我个人对语法糖的评价是非常高的,也许这个糖的原理并不复杂,比如我之前提到的扩展方法,但我们认识它的原理是远远不够的,还得理解,为什么要有这玩意.
H3.em3(H2.em2(Helper1.em1(what))) VS what.em1().em2().em3()
上面后者省略了import H1 H2 H3的过程,综合起来工作量也没差太多
但真的就仅仅是写法和视觉上的优化吗?其实远远不止.
前者是,XXHelper里面有个方法,可以操作what这个类型并做一些事情,
后者是,what既然有这样的特质,那么它就应该拥有某样的能力
前者是思维先找到Helper,再找到具体方法,
后者是what自然而然的提示出,what就有这样的能力(ide的智能提示),我敲下what+ . 后,它的能力就展示在我面前了,而不需要我还去翻箱倒柜的找helper方法.

谈谈激进技术的风险和收益,与不同阶层人员关注点的不同.

我最早推进kt的时候,最大的阻力就是来自公司的架构师团队,他们的关注点是:
kt相比java,能提高性能吗?(不能,kt的性能与java极度接近但略小与java)
kt解决了什么java并不能解决的问题吗?(没有,kt只是让你更快更好的写java代码)
kt能减少项目bug,提高项目稳定性吗?(某种程度上来说有一定帮助,但更多是看人,这理由也不够强力)

那时候我只是个开发 leader,这种层面肯定是没有太大的决策权的,他们的想法我也理解,公司几百号开发,提高一点点效率,相比引入新技术栈的风险,肯定是稳定压倒一切啦.
后面在我的争取下,我在一个简单项目上少量使用kotlin作为试点,后来一些原因我离开了这个公司,去小公司当技术合伙人去了,现在那段kotlin代码应该还跑在公司的tomcat上面,其他人不去翻代码,他们也不会知道这是用kotlin写的吧?

posted @ 2017-07-05 15:08  碎景  阅读(5691)  评论(1编辑  收藏  举报