深入kotlin - 基础语法
Posted 颐和园
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入kotlin - 基础语法相关的知识,希望对你有一定的参考价值。
Import
同 Java 一样,位于同一包内的 class 不需要 import,否则需要 import。但可以指定别名:
import com.example.xxx as zzz
将 xxx 导入,并重命名为 zzz。
判断
if 比 swift 中有所扩展。比较特别的地方是支持三目运算(swift 中时 ? :
三目运算符):
a = if(c==b) c else b
甚至可以使用多行语句,最后一句的表达式自动返回(不需要 return):
str = if(a<0)
println( "a<0" )
"负数"
else if(a>0)
"正数"
else
"零"
Optional
和 Swift 一样,Kotlin 通过 ? 为所有类型提供 optional 封装。
val a:Int? = 0
判空可以用 == null,也可以用三元运算符 ?: (和 swift 一样):
var b = a?:0 // 若果 a 为空,b = 0,否则 b = a
或者 isNullOrEmpty() 函数(函数式写法,类似于 java 中的 orElse):
a?.isNullOrEmpty()
和 swift 一样,kotlin 支持可空链,只要上步调用为空,则不执行下一步调用:
a?.length?.plus(10)?.times(20)
Kotlin 会自动对Optional变量的“危险”操作进行判断,比如直接对一个 Int? 和一个 Int 进行乘法操作会报类型不匹配错误,不能通过编译:
b = a * 2
但如果在进行乘法之前进行了判空,则 kotlin 就不会报错了,编译通过:
if(a!=null)
b = a*2
判空操作
包含 3 个:
- !! 相当于强制解包(swift 中是 ! )
- ?: 从语义上说,这也是三元运算符 ?: 的一种,仅仅是第2个表达式省略了,没有必要像 swift 一样平白多引入一个不知所谓的 ?? 关键字
- as? 和 swift 相同
根类
所有的 kotlin 类型都继承自 Any,它就相当于 Java 中的 Object。
增强的 when
Kotlin 中,when 相当于其它语言中的 switch 语句,但进行了某种程度的增强:
when (a)
1 ->
...
2 ->
...
else ->
...
分支合并
如果多个分支条件所执行的语句一样,则可以对分支进行合并:
when (a)
1,2,3,4 ->
...
5 ->
...
else ->
...
这里,分支 1,2,3,4 被合并了,它们都执行相同语句块。
支持区间 (Range)
由于 1,2,3,4 是一个连续的数值区间,我们可以使用区间表达式:
when (a)
in 1..4 ->
...
5 ->
...
else ->
...
in 1…4 表示一个全封闭区间,该区间包含了左边界和右边界,整个区间刚好包含 1,2,3,4。
迄今为止,kotlin 中的 when 跟 swift 中的 switch 语句完全对等。不过是将 switch 换成了 when, case 换成了 ->,default 换成了 else。
不同的是,swift 的 switch 还支持模式匹配。
Return 不是必须的
在 java 中,如果函数有返回值,那么函数必须 return 一个值或表达式作为返回值。在 kotlin 中这个不是必须的,kotlin 会自动采用函数最后一条语句(或表达式)的返回值作为返回值,比如:
fun hello(i:Int)->String
when(i)
0 -> return "hello"
1 -> return "world"
else -> return "hello world"
可以等同于:
fun hello(i:Int)->String
when(i)
0 -> "hello"
1 -> "world"
else -> "hello world"
这里 when 语句就是函数的最后一条语句(同时也是表达式),因此 kotlin 会计算 when 表达式的值(即字符串"hello"、"world"和 “hello world” 的三者之一)作为函数返回值。
由于函数体只是一个表达式,我们可以用kotlin 中直接对函数赋值的写法,同时返回类型依靠类型推断。因此可以进一步简化为:
fun hello(i:Int) =
when(i)
0 -> "hello"
1 -> "world"
else -> "hello world"
数组遍历
可以使用 for each 快捷遍历:
for(item in array)
println(item)
通过下标遍历:
for(item in array.indices)
println("array[$i] = $array[i]")
同时遍历下标和元素:
for((index, value) in array.withIndex())
println("array[$index] = $value")
区间
全闭区间
Kotlin 用..
表示一个全封闭区间(swift 为 ...
),其本质是 Int 类所特有的 rangeTo 运算符。判断一个变量是否位于某个区间,使用 in 关键字:
if (a in 2..10) // 2..10 等价于 2.rangeTo(10)
println("in the range")
如果判断不在区间内,则使用 !in
关键字。
修改步进值
步进值用 step 关键字表示。
for (i in 2..10 step 2)
递减区间
区间也可以向下递进,使用关键字 downTo:
for(i in 4 downTo 1) // for(int i=4; i<=1; i--)
for(i in 10 downTo 2 step 4) // for(int i=10, i<=2; i-=4)
半开区间
在 Java 中用得更多的是半开区间(左闭右开)。在 Kotlin 中,半开区间用 until 关键字支持(swift 为 ..<
):
0 until 10 // 左闭右开区间,包含左边界,不包含右边界
in 不仅仅用于区间
in 关键字不仅仅可以用于区间,也可以用于集合,比如数组,用于判断某个值是否在集合中存在:
when
"world" in array -> println("world in collection") // 如果 world 存在于数组 array 中,则打印 world in collection
这里,when 完全可以取代传统的 if 语句(swift 中,则用 switch 取代 if)。
集合
kotlin 严格区分可变集合和不可变集合。
可变集合的只读视图
fun main(args: Array<String>)
val stringList:MutableList<String> = mutableListOf("hello","world","!") // 1
val readOnlyView: List<String> = stringList // 2
println(stringList)
stringList.add("welcome")
println(readOnlyView)
readOnlyView.clear() //3
- MutableList 类属于可变集合,而 List 属于不可变集合。
- 定义 stringList (可变集合)的只读视图 readOnlyView 。stringList 是 mutable 集合,将它赋给 readOnlyView,而后者是 unmutable 的,因此可以将后者称为前者的“只读视图”。
- 因为 readOnlyView 是 unmutable 的,因此 clear 方法不可用,编译器报错。
只读集合支持协变-子类赋给父类
关于协变,请参考“面向对象编程-范型-协变、逆变”一节。在集合中,只读集合是支持协变的,而协变只能用于读,不能用于写。
val arr = listOf<String>("aa","bb")
val arr1: List<Any> = arr
arr 是 List 类型,arr1 是 List 类型,因此第二句代码产生了协变,我们将一个子类 List 赋给了父类 List,导致 arr1 也被“意外”地降级为 List。由于只读集合天然支持协变,所以此句能够通过编译。
快照
val arr = mutableListOf<String>("aa","bb")
val arr1 = arr.toList()
arr.add("cc")
println(arr) // 1
println(arr1) // 2
- 打印 [aa, bb, cc]
- 打印 [aa, bb]
toList 是一个快照方法,它会复制原集合中的元素形成一个“快照”,无论原集合此后发生任何变化,快照中的内容不会改变。
集合的扩展方法
val arr = listOf(1,3,4,5) // 构造方法
println(arr.first()) // 访问第一个元素
println(arr.last()) // 访问最后一个元素
arr.filter it %2 == 0 .forEach println(it) // filter 过滤,forEach 遍历
println(arr.requireNoNulls()) // 如果集合中存在 null 元素,抛出 IllegalArgumentException,否则返回集合的 Iterable
if(arr.none it > 10 ) // 如果所有元素都满足 >10 的条件,返回 true,否则 false
println("没有大于10的元素")
println(arr.firstOrNull()) // 返回第一个元素,如果集合为空,返回 null
println(arr.lastOrNull()) // 返回最后一个元素,如果集合为空,返回 null
val map = hashMapOf("a" to 1, "b" to 2) // 用扩展方法构造
println(map["a"]) // 通过下标(key)访问 value
val map2: Map<String, Int> = HashMap(map) // 通过构造方法构造
println(map2)
集合的函数式操作
Kotlin支持函数式编程,比如常见集合操作 filter、map、sort、forEach 等:
array.filterit.length>5.mapit.toUpperCase().sorted().forEachprintln(it)
和 Java 8 差不多。需要注意的是 it 是第一个入参的默认参数名。相当于 swift 中的 %0。
以上是关于深入kotlin - 基础语法的主要内容,如果未能解决你的问题,请参考以下文章