Kotlin基础(二)——包、控制流、返回和跳转

源文件可能开始于包的声明

package foo.bar 
fun baz() {} 
class Goo {} 
// ...

源码中所有的内容(类和函数)都被包含在包的声明中。所以,上述例子中函数baz的全称是foo.bar.baz,类Goo的全称是foo.bar.Goo

如果包没有具体说明,那么该文件中所有内容都属于没有名称的默认包。

默认导入

每个Kotlin源文件都会默认导入数个包:

  • kotlin.*
  • kotlin.annotation.*
  • kotlin.collections.*
  • kotlin.comparisons.* (since 1.1)
  • kotlin.io.*
  • kotlin.ranges.*
  • kotlin.sequences.*
  • kotlin.text.*

根据不同的目标平台,再导入一些附加的包:

  • JVM:
    • java.lang.*
    • kotlin.jvm.*
  • JS:
    • kotlin.js.*

自定义导入

除了默认导入的包,每个文件可能包含他自己输入的指令。
我们既可以导入单个名称

import foo.Bar // 现在可以使用Bar而不需要其他的先决条件

也可以导入范围内所有可以访问的内容

import foo.* // foo 中所有的内容都可以访问

如果存在命名冲突,我们可以使用关键词as在本地重命名有冲突的实体来消除歧义。

import foo.Bar // Bar可以访问
import bar.Bar as bBar // bBar 表示'bar.Bar'

关键字import并不局限于导入类,还可以用来导入别的声明

  • 顶层函数和属性
  • 对象声明中的函数和属性
  • 枚举常量

不同于Java,Kotlin不支持单独import static句法,所有的这些声明都是用常用的import关键字。

顶层声明的权限

如果顶层声明的被标记成private,那么它只属于文件内部私有。

控制流

if表达式

在Kotlin中,if是一个表达式,即,if有返回值。因此没有三元运算符(条件?yes:no),因为if已经很好的扮演了这个角色。

// 传统使用方式
var max = a 
if (a < b) 
    max = b

// 使用else时
var max: Int 
if (a > b) {
    max = a 
} else {
    max = b 
}

// 当做表达式
val max = if (a > b) a else b

if分支可以使用代码块,块中的最后一个表达式就是改代码块的值。

val max = if (a > b) { 
    print("Choose a") 
    a 
} else { 
    print("Choose b") 
    b 
}

如果使用if作为表达式而不是语句(如:返回它的值或者赋值给一个变量),那么表达式就需要else分支。

when表达式

when替换C类编程语言的switch操作,它具有简单的格式,如下:

when (x) { 
    1 -> print("x == 1") 
    2 -> print("x == 2") 
    else -> { // Note the block 
        print("x is neither 1 nor 2") 
    } 
}

when用它的参数按顺序匹配所有的分支,直到满足某个分支条件。when也可以当做表达式或语句使用。如果当做表达式使用,那满足条件的分支就是整个表达式的值。如果当做语句使用,那每个分支的值将会被忽略。同if一样,每个分支可以是一个代码块,每个代码块的值就是该代码块内最后一个表达式的值。

如果多个案例都用相同的处理方式,那么分支条件可以用逗号绑定。

when (x) { 
    0, 1 -> print("x == 0 or x == 1") 
    else -> print("otherwise") 
}

还可以用任意的表达式当做分支条件,不仅仅是常量。

when (x) { 
    parseInt(s) -> print("s encodes x") 
    else -> print("s does not encode x") 
}

也可以用in!in检验序列或集合中是否存在某个值

when (x) { 
    in 1..10 -> print("x is in the range") 
    in validNumbers -> print("x is valid") 
    !in 10..20 -> print("x is outside the range") 
    else -> print("none of the above") 
}

另一方面,我们可以使用is!is检查值是不是一些特殊的类型。
需要注意的是,由于智能转换的作用,你可以直接访问类型的属性和方法而不需要直接转换。

fun hasPrefix(x: Any) = when(x) { 
    is String -> x.startsWith("prefix") 
    else -> false 
}

when还可以替换if-else``if使用,如果没有提供参数,分支条件便是一个简单的boolean表达式,当表达式值是true时,便会执行分支的代码。

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

for循环

for循环可以迭代任何提供了迭代器的对象。句法如下:

for (item in collection) print(item)

循环体可以是代码块

for (item: Int in ints) { 
    // ...
}

照之前所描述,for循环可以迭代任何提供了迭代器的对象,即:该对象有个成员(或扩展)函数iterator(),函数的返回类型有个成员(或扩展)函数next()还有个返回Boolean类型的成员(或扩展)函数hasNext()。、

所有的这三个方法都需要用operator标记

for寻短迭代数组是编译成基于索引的循环,因此它没有创建迭代器对象。

如果想要根据索引迭代数组或序列,可以按照下述方式:

for (i in array.indices) { 
    print(array[i]) 
}

迭代一个序列是在编译时做优化处理,没有创建额外对象。

或者,使用库函数withIndex()

for ((index, value) in array.withIndex()) { 
    println("the element at $index is $value") 
}

while循环

whiledo...while循环的工作原理同平常一样。

while (x > 0) { 
    x--
}

do {
    val y = retrieveData() 
} while (y != null)

循环内的break和continue

在循环内部,kotlin支持传统的breakcontinue操作。

返回和跳转

kotlin有三种跳转结构表达式:

  • return 默认情况下,从最近的封闭函数(或匿名函数)返回
  • break 中断最近的封闭循环
  • continue 处理最近循环中的下一步

所有的这些表达式都可以当做某个更大的表达式的一部分:

val s = x.name ?: return //name==null时,执行return

break和continue标签

Kotlin中任何表达式都可以标记为标签。标签通常有可识别的格式用后缀@标记。如:abc@,fooBar@都是合法的标签。给表达式贴上标签只需在其前面添加一个标签即可。

loop@ for (i in 1..100) { 
    // ...
}

现在我们可以使用标签执行breakcontinue

loop@ for (i in 1..100) { 
    for (j in 1..100) { 
        if (...) break@loop 
    } 
}

一个有资格使用标签的break跳转到被标签标记的循环右面的地方开始执行。continue处理循环的下一次迭代。

return到标签

Kotlin中与函数式、本地函数和对象表达式对比,函数可以嵌套。有资格return的地方允许我们返回到外层函数。最重要的使用案例是从lambda表达式中返回。当我们这样写时会调用。

fun foo() { 
    ints.forEach { 
        if (it == 0) return 
        print(it) 
    } 
}

return表达式从最近的函数返回,即 foo。注意,这种非本地返回只支持传递给内联函数的lambda表达式。如果我们需要从lambda表达式返回,我们需要先标记才可以。

fun foo() { 
    ints.forEach lit@ { 
        if (it == 0) return@lit 
        print(it) 
    } 
}

现在,它只从lambda表达式返回。通常情况下,使用隐式标签非常方便。这样的标签与lambda传递的函数的名称相同。

fun foo() { 
    ints.forEach { 
        if (it == 0) return@forEach 
        print(it) 
    } 
}

或者,我们把lambda表达式替换成一个匿名函数。一个匿名函数内部的返回语句会从他本身返回。

fun foo() { 
    ints.forEach(fun(value: Int) { 
        if (value == 0) return  
        print(value) 
    })
 }

当我们返回一个值时,解析器会优先选择有资格返回,即:

return@a 1

表示给标签@a返回1,而不是返回一个标签表达式@a 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值