解构声明
//解构声明,一个解构同时创建多个变量
val (name, age) = person
//单独使用它们:
println(name)
println(age)
//解构声明会被编译成以下代码
val name = person.component1()
val age = person.component2()
可能遍历一个映射(map)最好的方式就是这样:
for ((key, value) in map) {
// 使用该 key、value 做些事情
集合
Kotlin区分可变集合和不可变集合
- Kotlin 的
List<out T>
类型是一个提供只读
操作如 size、get等的接口。改变 list 的方法是由MutableList<T>
加入的。- 这一模式同样适用于
Set<out T>
/MutableSet<T>
及Map<K, out V>
/MutableMap<K, V>
。
val numbers: MutableList<Int> = mutableListOf(1, 2, 3)
val readOnlyView: List<Int> = numbers
println(numbers) // 输出 "[1, 2, 3]"
numbers.add(4)
println(readOnlyView) // 输出 "[1, 2, 3, 4]"
readOnlyView.clear() // -> 不能编译
val strings = hashSetOf("a", "b", "c", "c")
assert(strings.size == 3)
当调用集合的时候只能用标准库的方法:listOf()、 mutableListOf()、 setOf()、 mutableSetOf()
list和set的扩展方法
val items = listOf(1, 2, 3, 4)
items.first() == 1
items.last() == 4
items.filter { it % 2 == 0 } // 返回 [2, 4]
val rwList = mutableListOf(1, 2, 3)
rwList.requireNoNulls() // 返回 [1, 2, 3]
if (rwList.none { it > 6 }) println("No items above 6") // 输出“No items above 6”
val item = rwList.firstOrNull()
区间
区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成
if (i in 1..10) { // 等同于 1 <= i && i <= 10
println(i)
}
//当调用这个方法的时候,是什么都不会输出来的
for (i in 4..1) print(i) // 什么都不输出
//要用到标准库中定义的"downTo()"函数
for (i in 4 downTo 1) print(i) // 输出“4321”
step()函数
for (i in 4 downTo 1 step 2) print(i) // 输出“42”
until 函数
for (i in 1 until 10) { // i in [1, 10) 排除了 10
println(i)
}
一些实用函数
rangeTo()
/downTo()
/reversed()
/step()
类型的检查与转换“is”与“as”
我们可以在运行时通过使用 is 操作符或其否定形式 !is 来检查对象是否符合给定类型:
if (obj is String) {
print(obj.length)
}
if (obj !is String) { // 与 !(obj is String) 相同
print("Not a String")
}
else {
print(obj.length)
}
When表达式
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // 注意这个块
print("x is neither 1 nor 2")
}
}
For循环
for (item in collection) print(item)
有一个成员函数或者扩展函数 iterator(),它的返回类型
有一个成员函数或者扩展函数 next(),并且
- 有一个成员函数或者扩展函数 hasNext() 返回 Boolean。
如果你想要通过索引遍历一个数组或者一个 list
,你可以这么做:
for (i in array.indices) {
print(array[i])
}
或者你可以调用库函数:withIndex
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
While循环
while (x > 0) {
x--
}
do {
val y = retrieveData()
} while (y != null) // y 在此处可见
This表达式
要访问来自外部作用域的this,我们可以使用this@label
class A { // 隐式标签 @A
inner class B { // 隐式标签 @B
fun Int.foo() { // 隐式标签 @foo
val a = this@A // A 的 this
val b = this@B // B 的 this
val c = this // foo() 的接收者,一个 Int
val c1 = this@foo // foo() 的接收者,一个 Int
val funLit = lambda@ fun String.() {
val d = this // funLit 的接收者
}
val funLit2 = { s: String ->
// foo() 的接收者,因为它包含的 lambda 表达式
// 没有任何接收者
val d1 = this
}
}
}
}
空安全
在Kotlin中String 类型的常规比变量不能容纳null
var a: String = "abc"
a = null // 编译错误
如果允许为空,我们可以声明一个变量为可空字符串,写作String?
var b: String? = "abc"
b = null // ok
在条件中检查null
val l = if (b != null) b.length else -1
安全的调用
使用安全调用操作符,写作?.
b?.length
,:如果b非空,就返回 b.length,否则返回 null,这个表达式的类型是 Int?
Elvis 操作符
val l = b?.length ?: -1
如果?:
左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
// ……
}
!! 操作符
我们可以写 b!! ,这会返回一个非空的 b 值 (例如:在我们例子中的 String)或者如果 b 为空,就会抛出一个 NPE 异常:
val l = b!!.length
可空类型的集合
如果你有一个可空类型元素的集合,并且想要过滤非空元素,你可以使用 filterNotNull 来实现。
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()
反射
函数引用
例如传给另一个函数。 为此,我们使用 :: 操作符:
fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd)) // 输出 [1, 3]
//这里 ::isOdd 是函数类型 (Int) -> Boolean 的一个值。
属性引用
要把属性作为 Kotlin中 的一等对象来访问,我们也可以使用 :: 运算符:
var x = 1
fun main(args: Array<String>) {
println(::x.get()) // 输出 "1"
::x.set(2)
println(x) // 输出 "2"
}