深入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

  1. MutableList 类属于可变集合,而 List 属于不可变集合。
  2. 定义 stringList (可变集合)的只读视图 readOnlyView 。stringList 是 mutable 集合,将它赋给 readOnlyView,而后者是 unmutable 的,因此可以将后者称为前者的“只读视图”。
  3. 因为 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
  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<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 - 基础语法的主要内容,如果未能解决你的问题,请参考以下文章

深入kotlin- 基础语法

深入kotlin- 基础语法

深入kotlin - 基础语法

深入kotlin - 基础语法

Kotlin -特殊用法详解

Kotlin -特殊用法详解