原本按照次序,这一波应该看 coroutine 相关的内容。不过考虑到这个东西对我近期的应用场景无关,所以跳过直接上 more language constructs 这一节了。
https://kotlinlang.org/docs/reference/multi-declarations.html#destructuring-declarations
这是个好东西,配合 data class
食用风味上佳。
data class Result(val result: Int, val status: Status)
fun function(...): Result {
// computations
return Result(result, status)
}
// Now, to use this function:
val (result, status) = function(...)
https://kotlinlang.org/docs/reference/typecasts.html#type-checks-and-casts-is-and-as
Kotlin 在 type cast 上还是做了些工作的,当然这边多数内容在 introduction 那一节已经介绍过了。这边值得一提是 Kotlin 在 type erasure 的限制下做了一些努力:
inline fun <reified T> List<*>.asListOfType(): List<T>? =
if (all { it is T })
@Suppress("UNCHECKED_CAST")
this as List<T> else
null
这个函数挺有用。运行时虽然不知道这个 List<*> 的类型参数是啥,但是可以用一个检查来安全的 cast 成 List<T>,省掉了一些 Java 中必须用 clazz<T> 来做的 trick。
https://kotlinlang.org/docs/reference/this-expressions.html#this-expression
意料之中。
https://kotlinlang.org/docs/reference/equality.html#equality
意料之中,==
代表 equals
,===
代表引用同一个对象。另外浮点数的判等还是坑。
https://kotlinlang.org/docs/reference/operator-overloading.html#operator-overloading
运算符重载的设计中规中矩。一个特定的运算符式子映射到一个特定的函数调用,确实清楚。
a + b => a.plus(b)
https://kotlinlang.org/docs/reference/null-safety.html#null-safety
利用类型系统避免 NPE 的思路是对的。然后这个链式调用的语法糖我喜欢:val name = bob?.department?.head?.name
。
https://kotlinlang.org/docs/reference/exceptions.html#exceptions
异常方面,try / catch 可以当表达式用:
val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }
另外取消了 checkedException 这事真是大快人心。
这边也解释了一下为什么要引入 Nothing
,基本说法是这玩意用来标记不可到达的代码位置。比如说一个函数总是抛异常而不返回,它的返回值类型就是 Nothing
。这个有一定道理,相较于返回 Unit
类型、也就是正常返回但是并不返回有意义的值的函数,这两种情况语义上是有微妙差别的。当然这个设计是不是划算,感觉也很难说。
https://kotlinlang.org/docs/reference/annotations.html#annotations
没啥可说的,基本和 Java 的设计一致。
https://kotlinlang.org/docs/reference/reflection.html#reflection
很意外的是没有看到 forName 之类的操作。反射不支持这个?太奇怪了。
https://kotlinlang.org/docs/reference/scope-functions.html#scope-functions
这个我是真不太明白 Kotlin 设计者的脑回路 …… 下面两段代码有啥区别?为啥非要说前一段「more concise and readable?」
Person("Alice", 20, "Amsterdam").let {
println(it)
it.moveTo("London")
it.incrementAge()
println(it)
}
// 对比
val alice = Person("Alice", 20, "Amsterdam")
println(alice)
alice.moveTo("London")
alice.incrementAge()
println(alice)
表示对这个特性实在喜欢不起来。能删掉的话,我投一票。
https://kotlinlang.org/docs/reference/type-safe-builders.html#type-safe-builders
这个有点意思。文档给出的例子代码值得一看:
import com.example.html.* // see declarations below
fun result() =
html {
head {
title {+"XML encoding with Kotlin"}
}
body {
h1 {+"XML encoding with Kotlin"}
p {+"this format can be used as an alternative markup to XML"}
// an element with attributes and text content
a(href = "http://kotlinlang.org") {+"Kotlin"}
// mixed content
p {
+"This is some"
b {+"mixed"}
+"text. For more see the"
a(href = "http://kotlinlang.org") {+"Kotlin"}
+"project"
}
p {+"some text"}
// content generated by
p {
for (arg in args)
+arg
}
}
}
学过 Kotlin 中以 lambda 表达式为参数的函数调用语法和运算符重载语法之后,这个例子其实不难看懂。但效果确实有点小惊艳。这个地方看,Kotlin 对实现 DSL 确实是下了功夫的。这里也得说一句,之前我对「以 lambda 表达式为参数的函数调用语法有特殊处理」这个设计颇有微词,吐槽过两次没价值。放到这里来看,却是「特殊」得正好,也不知道是有意设计的还是无心插柳。总之之前的抱怨看来要收回了,:P
https://kotlinlang.org/docs/reference/opt-in-requirements.html#opt-in-requirements
这个感觉不太重要,跳过了。