先来说说一些Kotlin的基本特点:
- Kotlin和Java一样是一门静态语言,这意味着所有表达式的类型在编译期已经确定了。
- Kotlin的运行时库体积非常小,所以不会导致你使用了Kotlin以后程序体积增大很多
- Kotlin程序的代码简洁,这是Kotlin最让人印象深刻的地方,这得益于Kotlin简洁的语法和函数式编程在Kotlin中的广泛使用。当然语法更简洁,必然就需要编译器做更多的事情,所以Kotlin完全重新编译一个工程的速度是比Java要慢点,不过在增加编译点时候却能够提供更快的编译性能。
- Kotlin另一个亮点是空安全。我们不必再为冷不丁冒出来的空指针异常而烦恼,因为Kotlin默认是空安全的,他会在编译阶段就检查潜在的空指针异常并提示你,而不是在运行期以让程序崩溃的方式来警告你。
- 和Java良好的互操作性。Kotlin一开始就瞄准了与现有的Java项目的集成问题,所以官方说他们能完美的与Java实现相互操作。
对于这点,我个人还是有一些疑虑的,毕竟Kotlin语言中有不少的特性在Java中是没有的,虽然的确能够做到相互操作,不过需要开发人员在遇到这些特性的时候做一些特殊的处理,否则会发生一些与预期不符的行为。这些以后我们谈到相关特性的时候再来讨论。
既然是学习笔记,接下来还是来点实际的吧,我们来看看Kotlin基本语法中的一些特别的点。
- 有且只有表达式体函数的返回类型可以省略:
比如,
fun max(a: Int, b: Int): Int = if (a > b) a else b
我们可以写成
fun max(a: Int, b: Int) = if (a > b) a else b
- 在Koltin中你可以像脚本语言中一样,在双引号字符串里引用其他变量
var name = "Leonard Messi"
println("Hello, $name!")
你还可以这样写
println("Hello, ${args[0]}!") // args是一个数组
甚至还可以这样写
println("Hello, ${if (args.size > 0) args[0] else "someone"}!")
- 在Kotlin中,if是表达式,而不是语句,它和 Java 中的三元运算符相似:
(a > b) ? a : b
,所以我们就有这样的代码
var name = if (a > b) a else b
- 如果你想定义全局静态常量,那你需要用到
const
关键字
const val UNIX_LINE_SEPARATOR = "\n"
它等价于
public static final String UNIX_LINE_SEPARATOR = "\n";
- Kotlin中的可变参数于Java类似,但语法略有不同,我们不使用三个点,而是
vararg
关键字
fun listOf<T>(vararg values: T): List<T> { ... }
val list = listOf(2, 3, 5, 7, 11)
- 展开操作符,是不是很方便?
fun main(args: Array<String>) {
val list = listOf("args: ", *args) //展开运算符展开数组内容
println(list)
}
- 解构声明,同时定义多个变量
val map = mapOf(1 to "one", 7 to "seven", 53 to "fifty-three") // define a map
val (number, name) = 1 to "one"
或者
for ((index, element) in collection.withIndex()) {
println("$index: $element")
}
-
局部方法,可以让代码更整洁
-
安全调用运算符:当你使用可空类型变量又不想空指针异常将整个程序搞崩溃时使用
fun printAllCaps(s: String?) {
// allCaps 可能是 null
val allCaps: String? = s?.toUpperCase()
println(allCaps)
}
>> printAllCaps(null)
null
- Elvis运算符
?:
,它通常与安全调用运算符结合使用
fun strLenSafe(s: String?): Int = s?.length ?: 0
如果s?.length
为null,那么函数的返回值是0。通常我们在第二个表达式的地方处理异常情况,比如throw一个异常,返回并退出函数等。
- 安全转换符
as?
:as?
运算符尝试把值转换成指定的类型,如果值不是合适的类型就返回null
val otherPerson = o as? Person ?: return false // 这里也结合了Elvis运算符一起使用
- 非空断言符
!!
,类似Java中 调用Assert语句
fun ignoreNulls(s: String?) {
// 如果发现s真的为空,会抛出空指针异常
val sNotNull: String = s!!
println(sNotNull.length)
}
因为Kotlin是空安全的,空指针并不出导致程序异常退出,非空断言在你需要显示的抛出异常时派上用场。(我记得某位同事在当初看到空安全概念时,提到过这个问题)
-
let
函数,可以被任何对象调用,但只有当调用对象非空时,才会执行后续的表达式操作,并且可以将调用对象作为表达式的参数使用;如果调用对象为空,将什么都不做
email?.let { email -> sendEmailTo(email) }
- 延迟属性的初始化,我们使用
lateinit
关键字
private lateinit var myService: MyService
这样,属性myService的初始化就需要一定要在构造函数中去完成了。但要注意延迟初始化的属性都是var,因为你需要在构造方法外修改它的值。
-
可空类型的扩展函数
在 Java 中,this永远是非空的,因为它引用的是当前你所在这个类的实例。而 在 Kotlin 中,这并不永远成立:在可空类型的扩展函数里,this可以为null。 -
数据类型的一些特点
- Kotlin 中所有基本数据类型都是引用对象,而any是所有对象的跟,类似Object
- Kotlin 新增了一种Unit类型,类似void,但Unit可以作为类型参数
- Nothing 类型,没有任何值,在异常处理中有用
- 数组: Koltin中用一个类 Array<>来表示
Array<String>(26) { i -> ('a' + i).toString() }
Kotlin标准库提供给了很多方便函数,toTypedArray
,forEachIndexed
等
- 集合(关于集合,内容不少,详情请参考《Kotlin In Action》)
- Kotlin 提供的大量的集合操作函数,使用非常方便,比如filter,map,sort,sum,filterNotNull等
- Kotlin 使用Java提供的集合为基础,增加了序列(sequence,用于实现惰性操作)
- 每一个Java集合在Kotlin中都有两个版本,一个只读,一个可修改
总结:
以上是对《Kotlin In Action》第一部分的内容当中的一些要点做了一个梳理,仅供参考。由于篇幅有限,不可能对每个点进行非常详细的阐述,如果想要了解更多的细节,请阅读原书。作者参与翻译的中文版《Kotlin实战》已经翻译完毕,已经在2017年8月正式上市,这是国内第一本权威且全面深入的kotlin教程,值得你拥有!
网友评论