用Kotlin一段时间了,主要是用来做本地数据分析,需要大量的字符串和集合处理,用原生Java着实麻烦了点。Python虽然也可以用,奈何公司自研的分布式数据库只支持Java访问,只能找一个JVM语言来用了。
Groovy和Scala都尝试过:
Groovy对Java兼容的实在是太细致入微了(我曾经把Java代码原样贴到Groovy脚本里,直接运行无压力),以至于我根本没有动力按照Groovy的最佳实践来进行开发。而且,不论是自己的实践还是第三方测评都已经证明了Groovy的性能相较于于原生Java差一倍左右。
Scala则是另一个极端,它提供了极其复杂的设计,上手的速度让人难以接受。此外,其编译的速度同样让人难受;再此外,无论是Eclipse还是Idea对Scala的支持都不是很美好(至少在我尝试Scala的时候是这样的)。
Kotlin则不同,JetBrains公司自己设计的语言,Idea对其支持是全面而深入的(根本不会出现代码提示的时候卡顿的情况,Scala呵呵哒)。当Google宣布Kotlin成为Android官方开发语言的时候,另一种叫做巨头站队的确定性加入到这门语言中。Kotlin对Java语法的支持是很节制的,甚至在Idea层面上,从Java拷贝的代码到Kotlin文件中,会做好自动转化而不是原样输出。
出于规避Oracle大流氓的角度考虑,切换其他的JVM语言是需要认真考虑的事情。虽然直接切换到其他平台,例如Go,也是可以考虑的,然而这将导致巨大的重写成本以及基础库的切换成本,我司自研数据库的访问就是一个例子。
以上。
在我使用Kotlin的这段时间里,从需求场景出发,最大的体会是它相当顺手的语法特征以及几乎没有门槛的切换,相对于原生Java来说,对我是相当可口的语法糖。本文不是严谨的一步步的语法教程,也不是详细的对比介绍,仅仅是使用过程中对Kotlin方便好用感触较深的点做相对全面的记录。基
础语法可以参考 kotlincn.net。
第一眼差别
顶层属性 和 顶层函数
其实顶层函数和顶层属性的意义是差不多的,很像脚本的写法,不需要包裹在一个Class或者Object中,而单独在脚本中出现。
静态函数是不包含状态的,也就是所谓的纯函数,它的输入仅仅来自于它的参数列表,那么调用的时候需要通过一个对象或者类中是非常多余的,因此在Kotlin中认为一个函数或方法有时候并不是属于任何一个类,它可以独立存在。
顶层属性和顶层函数的作用于是包,即同一个包中可以不用Import而直接调用。而跨包的调用则需要Import。
原理上,顶层文件会反编译成一个容器类。(类名一般默认就是顶层文件名+”Kt”后缀,注意容器类名可以自定义,通过@JvmName),顶层函数会反编译成一个static静态函数
Main函数可以作为顶层函数
直接作为顶层函数,可以没有类定义而直接运行。偏向于脚本的形式。
val(常量)、var(变量)、lateinit、by lazy{}
Kotlin中val之定义并赋值之后就无法变更的量,相当于Java中的final变量。而var则是可变量。在函数式编程中,是推荐尽量使用减少var,可变量在使用过程中很容易出现线程不安全的情况。具体参见 “理解Scala的函数式风格:从var到val的转变”。Scala和Kotlin在这一点上是一致的。
kotlin中默认是空安全的,任何属性的声明都必须有初始化值,如果支持可空”?”,才能把属性声明为null。那么一个非空的变量如果需要在后面赋值,则需要用lateinit。lateinit var只能用来修饰类属性,不能用来修饰局部变量,并且只能用来修饰对象,不能用来修饰基本类型(因为基本类型的属性在类加载后的准备阶段都会被初始化为默认值)。lateinit var的作用也比较简单,就是让编译期在检查时不要因为属性变量未被初始化而报错。lateinit可以在任何位置初始化并且可以初始化多次。
而 val 的延迟初始化则是要用 by lazy { 代码块 }。by lazy只能作用于val关键字标注的属性。当属性用到的时候才会初始化”lazy{}”里面的内容,而且再次调用属性的时候,只会得到结果,而不会再次执行lazy{}的运行过程。
类型推断
kotlin类型名首字母是大写的 变量名是小写的 以示区分。形式定义为:var 变量名 : 类型名 = 值。对于基本数据类型,可以直接省略类型名,而由系统进行类型推断。
Import
如果出现名字冲突,可以使用 as 关键字在本地重命名冲突项来消歧义:
import foo.Bar // Bar 可访问
import bar.Bar as bBar // bBar 代表“bar.Bar”
可读的数字
val creditCardNumber = 1234_5678_9012_3456L
常见功能简化:
println() 等同于 System.out.println()。
不需要“new”关键字 val rectangle = Rectangle(5.0, 2.0)
强制类型转换:”123“.toInt() 看上去更加顺畅
‘==‘和‘===‘的区别,双等号比较kotlin团队的处理就是通过Intrinsics.areEqual(b, c)来比较两个对象的值是否相等,三个等号就是通过java中的‘==‘比较两个对象的地址是否相等。
类型判断:obj is String
属性默认为final,除非申明为 open(跟val一样的原因,不推荐使用可变量)
没有Object类型,只有Any
Kotlin中所有的类都有一个共同的基类Any,如果类没有申明继承其他类的话,默认继承的就是Any。它只有三个方法,equals,hashCode和toString。而去掉了Object关于同步相关的函数(wait, notify等)。
?和!!
"?"加在变量名后,系统在任何情况不会报它的空指针异常,用于显式标记变量可以为空。"!!"加在变量名后,如果对象为null,那么系统一定会报异常,用于显式标记变量绝对不能为空。这两个符号能让开发者明确对变量空值的感知。任何一个变量,如果不加上?,相当于默认加上了!!。
roomList?.size 返回的是 null 或者是 roomList的大小。
字符串相关
多行字符串:
你可以通过 trimMargin() 函数去除前导空格: