【深入kotlin】 - 基础语法(二)

【深入kotlin】 - 基础语法(二),第1张

【深入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) {
    val stringList:MutableList = mutableListOf("hello","world","!") // 1
    val readOnlyView: List = stringList // 2

    println(stringList)

    stringList.add("welcome")

    println(readOnlyView)

    readOnlyView.clear() //3
}
  1. MutableList 类属于可变集合,而 List 属于不可变集合。
  2. 定义 stringList (可变集合)的只读视图 readonlyView 。stringList 是 mutable 集合,将它赋给 readOnlyView,而后者是 unmutable 的,因此可以将后者称为前者的“只读视图”。
  3. 因为 readonlyView 是 unmutable 的,因此 clear 方法不可用,编译器报错。
只读集合支持协变-子类赋给父类

关于协变,请参考“面向对象编程-范型-协变、逆变”一节。在集合中,只读集合是支持协变的,而协变只能用于读,不能用于写。

    val arr = listOf("aa","bb")
    val arr1: List = arr 

arr 是 List 类型,arr1 是 List 类型,因此第二句代码产生了协变,我们将一个子类 List 赋给了父类 List,导致 arr1 也被“意外”地降级为 List。由于只读集合天然支持协变,所以此句能够通过编译。

快照
   val arr = mutableListOf("aa","bb")

    val arr1 = arr.toList()
    
    arr.add("cc")
    println(arr) // 1
    println(arr1) // 2
  1. 打印 [aa, bb, cc]
  2. 打印 [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 = HashMap(map) // 通过构造方法构造
    println(map2)
集合的函数式 *** 作

Kotlin支持函数式编程,比如常见集合 *** 作 filter、map、sort、forEach 等:

array.filter{it.length>5}.map{it.toUpperCase()}.sorted().forEach{println(it)}

和 Java 8 差不多。需要注意的是 it 是第一个入参的默认参数名。相当于 swift 中的 %0。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5609491.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存