Kotlin的语法糖们
- 1. 字符串模板(string template)
- 2. 分号推断(semicolon inference)
- 3. 定义函数(define function)
- 4. var/val(local variable)
- 5. 可空值(nullable value)
- 6. 集合字面量(collection literals)
- 7. when表达式(when expression)
- 8. is运算符(is operator)
- 9. 范围运算符(range)
- 10. 运算符重载(operator overloading)
- 11. 包别名(package alias)
- 12. 类型别名(type alias)
- 13. 扩展函数(extension function)
- 14. 函数扩展(function expansion)
- 15. 默认参数(default arguments)
- 16. 单例对象(singleton)
- 17. 伴生对象(companion object)
- 18. getter和setter(getter and setter)
- 19. 数据类(data class)
- 20. 没有原始类型(no raw types)
- 21. 没有受检查异常(no checked exception)
- 22. 没有static(no static member)
- 23. 多返回值(multiple return values)
- 24. 嵌套块注释(nested block comment)
- 25. 在线版IDE
当今的Kotlin真是炙手可热啊。自2011年JetBrains为了提高IDEA的销量而推出这个项目至今,它一直低调而稳定地发展着。到了上个月即2017年5月,Google宣布将Kotlin语言作为Android开发的一级编程语言,算是到达了语言生的第一个巅峰。Kotlin自身受到Java、C#、JavaScript、Scala、Groovy等语言的影响,本文总结了它提供的部分常见语法糖并与其它语言进行比较。
字符串模板(string template)
Kotlin可以直接通过println("Hello, {name}")
或println("Hello, $name")
来使用字符串模板,而Java则需要先借助String.format
来生成字符串。而kotlin还支持表达式,如${person.name}
和${2 * 3}
。这块古老的糖从shell开始就有了:
如果你疑惑为什么无须导入包即可直接使用println
,那是因为这个方法所在的kotlin.io
包是默认导入(Default Imports)的,正如Java会默认导入java.lang.*
一样。Kotlin的默认导入请参考这里。
分号推断(semicolon inference)
我们知道Java中的每一条语句结束后,需要加上分号。Kotlin中的分号是可选的。这应该是来自JavaScript吧。不过写JavaScript还是推荐把分号都加上,否则可能有危险。Groovy、Scala也有同样的能力。
定义函数(define function)
JavaScript中,function
;Go语言,func
;Kotlin,fun
。怎么看都像是SIM卡变成了micro-SIM,然后又变成了nano-SIM卡。Kotlin可以在类之外定义全局函数,也可以在函数中定义局部函数。这一点类似于JavaScript。
var/val(local variable)
变量是var
,表示variable;常量是val
,表示fixed value。这个很明显来自Scala。在Java中就只能用final
关键字了。
可空值(nullable value)
在变量类型后面加上一个问号,表明这个变量可以为null,否则默认不能为null。例如:
这一句编译错误:var a: Int = null
这样才能成功:var a: Int? = null
这块糖显然来自于C#,但是更加严格了。它是为了避免Java中的null所造成的十亿美元的错误。
集合字面量(collection literals)
Java从来就不愿意用糖吸引小朋友……所以一般快速创建集合是这么写的:
有好事者(Guava)提供了这样的类库:
其实Java 8提供的Stream也许已经能够满足你的需求:
Java 9很可能会引入集合字面量:
Kotlin出手了:
不过实际上并非是语法层面的糖,listOf
只是一个方法而已。我相信是从Scala中偷师的:
当然Scala还有自己的经典方式:
C#可以这样来初始化集合:
JavaScript、Ruby、Go等直接扩展了数组,所以就更省心了。
when表达式(when expression)
when
表达式有点像是不需要break
的switch…case
:
但它还可以做得更多:
可以把它作为扩展版if…else
来用。它有点类似Groovy的switch
。
is运算符(is operator)
先看代码:
在这里,obj is String
之后就可以将其作为String
来使用了,调用String
的length
属性。is
不仅比instanceof
更加短小精悍,而且还会自动将变量转换为is
后面的类型。应该是出于C#而胜于C#。C#提供了is
和as
,但是as
在Kotlin中显然就毫无用武之地了。
范围运算符(range)
Java如果要循环打印1至9,一般就是这样:
如果需要步长(step),lambda方案就需要引入filter、map或iterate。Kotlin自带接口ClosedRange
,用了点糖:
bash早就支持大括号配合..
(brace expansion)的这种方式了:
不过我更喜欢ruby,支持lambda的写法更加优雅:
运算符重载(operator overloading)
这个是C#和Scala的把戏:
怎么知道+
号上映射的是plus
方法呢?还是得参考官方文档。
包别名(package alias)
Kotlin支持为包指定别名,对代码洁癖患者可能会起到一定的疗效:
Python、Groovy也都是这样:
类型别名(type alias)
Kotlin还支持为类型指定别名:
这应该是来自Scala的Type:
扩展函数(extension function)
扩展函数允许为一个类增加公有静态方法,调用时就好像这个方法是原生的一样。
虽然JavaScript也能轻易做到,但我还是强烈地认为它来自于C#,毕竟都是一脉相承。kotlin更近一步支持扩展属性:
函数扩展(function expansion)
如果函数的最后一个参数类型是个函数,可以通过大括号来传值:
这应该是来自ruby的block:
默认参数(default arguments)
Kotlin支持为参数指定一个默认值:
Java一般是靠重载来实现默认参数。许多其它的语言都支持默认参数。例如,JavaScript在ES6上也支持默认参数了:
单例对象(singleton)
|
|
这应该是来自于Scala,连关键字都一模一样。
伴生对象(companion object)
伴生对象经常用于Factory。这一点相信也是来自于Scala。
getter和setter(getter and setter)
Kotlin像C#一样支持属性(property)。我们来看两个例子:
数据类(data class)
告别繁琐的Java数据类的时代到来了:
看到最前面的data
,我突然觉得这是源于lombok…
没有原始类型(no raw types)
Kotlin没有原始类型,一切皆对象:1.inc()
。这一点与Ruby、Scala相同。
没有受检查异常(no checked exception)
Kotlin并没有受检查异常。因为在大型的项目中,它对代码质量的提升极其有限,但是却大大降低了效率。C#十多年前就是这样了,有兴趣的读者可以参考这篇文章。
没有static(no static member)
Kotlin也没有static的成员。这一点与Scala相同。在Kotiln中可以使用包级别的函数,或者是伴生对象来实现static的效果。
多返回值(multiple return values)
可以从这一个例子中看到Kotlin是如何实现函数的多返回值的。我猜应该是受到了Go语言的启发。
嵌套块注释(nested block comment)
Kotlin支持块注释/* … */
的嵌套。这可能是来自Haskell或F#。
在线版IDE
如果不想安装那么多语言,可以试试这个在线版IDE,它支持包括Kotlin在内的几十种语言。