Kotlin专题「四」:逻辑控制语句(if、for、when、while、return、break、continue)
前言: 有些路看起来很近,可是走下去却很远,缺少耐心的人永远走不到尽头。人生,一半是现实,一般是梦想。
一、概述
前面几篇文章中讲解了 Kotlin 的常量、变量、数据类型和作用域函数等,与 Java 相比还是有一定的区别。这里给大家介绍 Kotlin 的相关逻辑控制语句,如:if
,for
,when
,while
等。Kotlin 中没有 Java 中的三元运算符,但是用if
语句可以实现类似效果;when
语句替代了 Java 中的 switch
语句;for
循环语句废除了 Java 中的(初始值;条件;增减步长)规则,新增了其他规则。下面我们来详细分析:
二、if语句
Kotlin 中的if
语句与 Java 中的语句有一定区别的,它在 Kotlin 中更灵活,除了能实现 Java 中的写法外,还可以实现表达式以及一个块的运用。一个if
语句包含一个布尔表达式(类似三目运算符)和一条或多条语句。
(1)传统用法
Kotlin 中的if
语句的传统用法与 Java 中的用法一样,没什么好说的,看代码:
val numA = 0val numB = 5var result = 10if (numA == 5) result = numAif (numA > numB) {result = numA} else {result = numB}
(2)表达式(三元运算符)
Kotlin 中其实不存在 Java 中的三元运算符条件表达式 ? 表达式1 : 表达式2
,因为 Kotlin 中的if
语句的表达式会返回一个值,所以不需要三元运算符。
//Java 的三目运算符 Kotlin中这样写会报错//int result = numA > numB ? 10 : 20;//kotlin 中直接使用 if…else…替代var result = if (numA > numB) {10} else {20}Log.e(TAG, "if语句:result == $result")//当numA>numB时,result=10,否则result=20//简写为var result = if (numA > numB) 10 else 20
打印数据如下:
if语句:result == 20
可以看到在 Kotlin 中if
语句可以作为一个表达式并且返回一个值。
三、for语句
Kotlin for
循环可以对任何提供迭代器(iterator)的对象进行遍历。循环数组会被编译为一个基于索引index
的循环,不会创建迭代器对象。for
循环语句废除了 Java 中的(初始值;条件;增减步长)规则,新增了其他规则。其语法如下:
for (item in collection){print(item)
{
- in: 运算符,表示在…之内的意思,使用
in
操作符来遍历。
3.1 递增(..
与until
)
..
与until
都是表示递增的区间,只是区间的取值范围不同。
..
: 创建从此值到指定值的范围。表示一个区间,该区间是闭区间,包括开始值和结束值,[n,m]。- until: 创建从此值但不包括指定的值的范围。表示一个区间,该区间是半闭区间,包括开始值,不包括结束值,[n,m)。
//java 的for循环递增
// for (int i = 0; i < 5; i++) {// System.out.println(i);
// }//循环5次,步长为1的递增for (i in 1..5) {//1 2 3 4 5print("$i \t")}//循环4次,步长为1的递增for (i in 1 until 5) {//1 2 3 4print("$i \t")}
打印数据如下:
for语句:..递增 == 1 2 3 4 5for语句:until递增 == 1 2 3 4
注意:区间是从小到大的,如果开始的数值比最后的还要大则没有意义。在until
中,如果[to]值,即最后的数值,这里为5,小于或等于当前值i
,则返回的数值为空。
3.2 递减downTo
Kotlin 使用downTo
表示递减。
- downTo: 通过步长-1返回从该值向下到指定的值的序列。表示一个区间,该区间是闭区间,包括开始值和结束值,[n,m]。
//循环5次,步长为-1的递减for (i in 5 downTo 1) {print("$i \t")}
上面的区间是5 downTo 1
,当前值i
必须大于或者等于[to]值,即1,如果当前值i
小于[to]值,则返回的数值为空。打印数据如下:
for语句:downTo递减 == 5 4 3 2 1
3.3 步长step
上面的例子中的步长都是为1,步长我们可以根据自己需求来设置:
- step: 返回与给定步骤执行相同范围的进程。也就是说取值的间隔是多少。
//step:步长为2,循环两次的递减for (i in 6 downTo 1 step 2) {print("$i \t")}
打印数据如下:
for语句:step步长为2 == 4 2
3.3 遍历字符串
for
循环也能遍历字符串,会把每个字符逐个打印出来。
//遍历字符串for (i in "HelloWord") {print("$i \t")}
打印数据如下:
for语句:字符串 == H e l l o W o r d
3.4 遍历集合
for
循环遍历集合:
//遍历集合val userArray = arrayListOf(User("姓名1"), User("姓名2"), User("姓名3"))for (item in userArray) {print("${item.name} \t")}
打印数据如下:
for语句:遍历集合 == 姓名1 姓名2 姓名3
3.5 通过索引遍历
如果你想通过索引遍历遍历集合或数组,可以使用indices
关键字。
- indices: 返回此集合的有效索引的
[int范围]
。
//indices比遍历val intArray = arrayListOf(10, 20, 30, 40)for (i in intArray.indices) {Log.e(TAG, "for语句:indices遍历 == intArray[$i]:${intArray[i]}")}
打印数据如下:
for语句:indices遍历 == intArray[0]:10
for语句:indices遍历 == intArray[1]:20
for语句:indices遍历 == intArray[2]:30
for语句:indices遍历 == intArray[3]:40
注意:这种“在区间上遍历”会编译成优化的实现而不会创建额外的对象。
3.6 库函数 withIndex
for
循环中的withIndex
返回一个惰性的[Iterable]
,它将原始集合的每个元素包装成一个IndexedValue
对象,其中包含该元素和元素本身的索引。IndexedValue
表示一个在集合或者序列中的值及其在该集合或序列中的索引的数据类型。源码如下:
public data class IndexedValue<out T>(public val index: Int, public val value: T)
来简单使用下:
//withIndex:包含该元素和元素索引val intArray = arrayListOf(10, 20, 30, 40)for ((index, value) in intArray.withIndex()) {Log.e(TAG, "for语句:withIndex == index: $index, value: $value")}
打印数据如下:
for语句:withIndex == index: 0, value: 10
for语句:withIndex == index: 1, value: 20
for语句:withIndex == index: 2, value: 30
for语句:withIndex == index: 3, value: 40
四、when 语句
when
将它的参数和所有分支条件比较,直到某个分支满足条件,跳出语句。when
既可以当做表达式使用也可以当做语句使用,如果被当做表达式,那么符合条件的分支的值就是整个表达式的值;如果当语句使用则忽略分支的值。when
操作符类似 Java 中的 switch
操作符,甚至可以替换if
语句。
4.1 普通用法
when
操作符用 ->
表示要执行的操作,类似switch
的:
,同时每个分支不需要像switch
语句那样添加break
跳出分支,如果分支下面只有一个语句,则可以省略块符号{}
,否则需要加上块符号{}
将要执行的操作包起来。
//Java的 switch 语法int num = 0;switch (num) {case 2:System.out.print("switch语句:num == 2");break;case 4:System.out.print("switch语句:num == 4");break;default:System.out.print("switch语句:num != 2 && num != 4");}//Kotlinvar num = 0when (num) {2 -> print("when语句:num == 2")4 -> {print("when语句:num == 4")}else -> {//注意块, else 等同于java中的 defaultprint("when语句:num != 2 && num != 4")}}
在when
中,else
的含义等同于 switch
中的 default
,如果其他分支不满足条件都会走else
分支。打印数据如下:
when语句:num != 2 && num != 4
4.2 分支处理方式相同
如果很多分支用相同的方式处理,则可以把多个分支条件放在一起,用,
分隔开来,相当于 switch
中不用break
跳转的语句:
var num = 2when (num) {//2,4分支相同的方式处理2, 4 -> print("when语句:num == 2 or num == 4")else -> print("when语句:num != 2 && num != 4")}
打印数据如下:
when语句:num == 2 or num == 4
4.3 条件使用任意表达式
when
语句中的条件可以使用任意表达式,并不是只局限于常量,相当于 if
表达式的用法:
when (num > 0) {true -> print("when语句:num > 0")false -> print("when语句:num < 0")}
打印数据如下:
when语句:num > 0
4.4 检查值是否在集合或者数组中
那么也可以检查一个条件是否在in
或者不在!in
一个区间或者集合中,in
表示在…范围内,!in
表示不在…范围内。
var num = 5val intArray = arrayOf(6, 7, 8, 9, 10)when (num) {in 1..5 -> print("when语句:num == 属于 1 ~ 5 中")!in intArray -> print("when语句:num == 不在intArray集合中")else -> print("when语句:num == 都不属于")}
打印数据如下:
when语句:num == 属于 1 ~ 5 中
4.5 检查值是否为指定类型的值
检测一个值是is
或者不是!is
一个特定的类型。注意:kotlin 的智能转换,可以访问该类型的属性和方法而不需要任何的检测。
fun isWhen(x: Any) = when (x) {is Int -> print("when语句:x 是Int类型")!is String -> print("when语句:x 不是String类型")else -> print("when语句:x 是String类型")}//调用isWhen("山水有相逢")
打印数据如下:
when语句:x 是String类型
4.6 不提供参数
when
也可以用来取代if … else
链,如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支条件为true时,则执行该分支,跳出语句。
var str = "kotlin"val strArray = arrayOf("android", "kotlin", "java")when {str is String -> print("when语句:str 是String类型")"java" in strArray -> print("when语句:java == 在集合中")}
打印数据如下:
when语句:str 是String类型
可以看到in
运算符还可以判断集合内是否包含某实例。
五、while与do…while语句
Kotlin 中的while
和do…while
语句与 Java 中的用法相同。while
语句如果不满足条件是不会进入循环的,不同的是do…while
是先执行循环再判断条件,循环至少会执行一次。
while
的结构如下:
while( 布尔表达式 ) {//TODO 循环内容}
while
的结构如下:
do {//TODO 循环内容}while(布尔表达式);
do...while
语句的使用:
var numA = 1while (numA < 6) {Log.e(TAG, "while语句:循环了$numA 次")numA++}
打印数据如下:
while语句:循环了1 次
while语句:循环了2 次
while语句:循环了3 次
while语句:循环了4 次
while语句:循环了5 次
do...while
语句的使用:
var numB = 0do {Log.e(TAG, "do...while语句:循环了$numB 次")numB--} while (numB > 0)
打印数据如下:
do...while语句:循环了1 次
六、返回和跳转语句(return、break、continue)
Kotlin 有三种结构化跳转:return、break、continue,和 Java 的用法和意义一致。
- return: 默认从直接包围它的函数或者匿名函数返回;
- break: 终止最直接包围它的循环;
- continue: 继续下一次最直接包围它的循环。即跳出本次循环,即系下一次循环。
另外,在 Kotlin 中任何表达式都可以使用标签来标记(label),标签的形式是标签名后接@
标识符,如flag@
等,标签符由自己决定:
flag@ for (i in 1 .. 10) { {
我们就可以使用一个标签限定一个 brea k或一个 continue,使用标签限定的 break 会跳到刚好位于该标签指定的循环后面的执行点,continue 继续标签指定的循环的下一个迭代。
6.1 break、continue和标签
在 Kotlin 中支持传统的 break 和 continue 操作符:
//基本用法for (i in 1..10) {if (i == 4) continue//i == 4时,跳出当前循环,进入下一次循环Log.e(TAG, "break和continue:i == $i")if (i > 6) break//i > 6时跳出循环}
打印数据如下:
break和continue:i == 1
break和continue:i == 2
break和continue:i == 3
break和continue:i == 5
break和continue:i == 6
break和continue:i == 7
现在,我们可以使用一个标签来定义一个 break 或 continue :
//使用一个标签来定义一个break或continue:Log.e(TAG, "=== break和标签一起使用 ===")loop1@ for (i in 1..10) {for (j in 1..10) {if (true) {Log.e(TAG, "break: i + j == $i + $j")break@loop1//跳出@loop1循环}}}Log.e(TAG, "=== continue和标签一起使用 ===")loop2@ for (i in 1..10) {for (j in 1..10) {if (true) {Log.e(TAG, "continue: i + j == $i + $j")continue@loop2//跳出本次循环,进入下一个@loop2循环}}}
打印数据如下:
=== break和标签一起使用 ===
break: i + j == 1 + 1
=== continue和标签一起使用 ===
continue: i + j == 1 + 1
continue: i + j == 3 + 1
continue: i + j == 4 + 1
continue: i + j == 5 + 1
continue: i + j == 6 + 1
continue: i + j == 7 + 1
continue: i + j == 8 + 1
continue: i + j == 9 + 1
continue: i + j == 10 + 1
可以看到使用一个标签限定一个 break 或一个 continue 后,使用标签限定的 break 会跳到刚好位于该标签指定的循环后面的执行点loop1@
,continue 继续标签loop2@
指定的循环的下一个迭代。
6.2 return和标签
Kotlin 有函数字面量,局部函数和对象表达式。所以 Kotlin 函数可以被嵌套,标签限制的 return 允许我们从外层函数返回,最重要的一个用途就是从 lambda 表达式中返回。普通使用:
private fun returnGrammar() {var intArrays = arrayListOf(1, 2, 3, 4)for (item in intArrays) {if (item == 2) returnLog.e(TAG, "return:item == $item")}Log.e(TAG, "return:外层函数")
}
打印数据如下:
return:item == 1
这个 return 表达式从最直接包围它的函数returnGrammar()
中返回,注意,这种非局部的返回只支持传给内联函数的 lambda 表达式,如果我们需要从 lambda 表达式中返回,我们必须加标签并用以限制return。
(1)标签和return一起使用
//1.标签和return一起使用
private fun returnGrammar() {var intArrays = arrayListOf(1, 2, 3, 4)//数组的迭代器理由有一个Iterable.forEach()方法,传入了一个it参数,为数组中的元素intArrays.forEach flag@{if (it == 2) return@flagLog.e(TAG, "return:item == $it")}Log.e(TAG, "return:外层函数")
}
可以看到,return@flag
只会从 lambda 表达式中返回,并未从外层函数中返回,继续执行输出了3,4
和外层函数
。打印数据如下:
return:item == 1
return:item == 3
return:item == 4
return:外层函数
(2)使用隐式标签,该标签与接受该 lambda 的函数同名
//2.使用隐式标签,该标签与接受该 lambda 的函数同名
private fun returnGrammar() {var intArrays = arrayListOf(1, 2, 3, 4)intArrays.forEach {if (it == 2) return@forEachLog.e(TAG, "return:item == $it")}Log.e(TAG, "return:外层函数")
}
通常使用隐式标签更方便,该标签与接受该 lambda 的函数forEach
同名。打印数据如下:
return:item == 1
return:item == 3
return:item == 4
return:外层函数
(3)使用匿名函数代替 lambda 表达式,返回是从匿名函数中返回而不是外层函数
//3.使用匿名函数代替 lambda 表达式,返回是从匿名函数中返回而不是外层函数
private fun returnGrammar() {var intArrays = arrayListOf(1, 2, 3, 4)intArrays.forEach(fun(value: Int) {if (value == 2) returnLog.e(TAG, "return:value == $value")})Log.e(TAG, "return:外层函数")
}
使用一个匿名函数替代 lambda 表达式,匿名函数内部的 return 语句将从该匿名函数自身返回。打印数据如下:
return:value == 1
return:value == 3
return:value == 4
return:外层函数
(4)注意前三个示例中使用的本地return类似于在常规循环中使用的 continue。对于 break 没有直接的等价,但是可以同过添加另一个嵌套 lambda 和非本地 return 来模拟:
private fun returnGrammar() {var intArrays = arrayListOf(1, 2, 3, 4)run loop@{intArrays.forEach {if (it == 2) return@loopLog.e(TAG, "return:@loop == $it")}}Log.e(TAG, "return:外层函数")
}
打印数据如下:
return:@loop == 1
return:外层函数
当要返回一个值的时候,解析器优先选择标签限制的 return:
return@flag 10
意思是从标签@flag
处返回10,而不是返回一个标签标注的表达式@flag 10
。
七、总结
Kotlin语句 | 含义 | 注意事项 |
---|---|---|
if(条件判断) | 一个if语句包含一个布尔表达式和一条或多条语句。 |
1. if 语句可以作为一个表达式并且返回一个值; 2.能实现 Java 的三目运算符和块级运用。 |
for(循环) | 对任何提供迭代器(iterator)的对象进行遍历 |
1.in 运算符,表示在…之内的意思,使用 in 操作符来遍历;2. .. 与until 都是表示递增的区间,只是区间的取值范围不同;3. downTo 表示递减,step 表示设置步长;4. indices 返回集合的有效索引;5. withIndex 返回一个IndexedValue对象包含该元素和元素本身的索引。
|
when(分支) | 将它的参数和所有分支条件比较,直到某个分支满足条件,跳出语句 |
1.-> 表示要执行的操作,类似 switch 的: ;2.分支下面只有一个语句,则可以省略块符号 {} ;3. else 的含义等同于 switch 中的default ;4.多个分支有相同方式处理,分支可以用逗号 , 隔开;5.条件可以使用任意表达式; 6.如果不提供参数,所有的分支条件都是简单的布尔表达式,为 true 则跳出语句。 |
while(循环) | 满足条件则执行下面的逻辑 | 不满足条件是不会进入循环。 |
do…while(循环) | 先执行逻辑再判断条件是否满足 | 先执行循环再判断条件,循环至少会执行一次。 |
return(跳出) | 默认从直接包围它的函数或者匿名函数返回 | 用法与 Java 类似,可以配合标签使用,如:return@loop。 |
break(跳出) | 终止最直接包围它的循环 | 用法与 Java 类似,可以配合标签使用,如:break@loop。 |
continue(跳出) | 继续下一次最直接包围它的循环。即跳出本次循环,即系下一次循环 | 用法与 Java 类似,可以配合标签使用,如:continue@loop。 |
源码地址:https://github.com/FollowExcellence/KotlinDemo-master
点关注,不迷路
好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才。
我是suming,感谢各位的支持和认可,您的点赞、评论、收藏【一键三连】就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !
要想成为一个优秀的安卓开发者,这里有必须要掌握的知识架构,一步一步朝着自己的梦想前进!Keep Moving!
Kotlin专题「四」:逻辑控制语句(if、for、when、while、return、break、continue)相关推荐
- Kotlin专题「二」:变量(var与val)、常量、注释
前言: 莫问良人长与短,从此山水不相逢. 一.概述 大家都知道 Kotlin 现在被 Gooogle 定为 Android 的官方开发语言.Kotlin 在项目中的使用将会越来越广泛,这也掀起了一 ...
- 从零开始学 Kotlin 之「2」数据类型
前言 大家好,这里是「从零开始学 Kotlin 之『2 』数据类型」,本文首发于公众号「Binguner」,欢迎前往大家关注.我会每周分享一些关于 Android 和其他方向的技术干货或一些关于认知的 ...
- 计算机网络「四」 网络层
本文为计算机网络系列第四章笔记,陆续会更新余下内容.文章参考:计算机网络微课堂 系列文章: 计算机网络「一」计算机网络概述 计算机网络「二」物理层 计算机网络「三」 数据链路层 需要说明:文章中图 ...
- CSS基础「四」浮动 \ 常见网页布局
本篇文章为 CSS 基础系列笔记第四篇,参考 黑马程序员pink老师前端入门教程 其他CSS基础相关文章: CSS基础「一」基础选择器 / 字体属性 / 文本属性 / 三种样式表 CSS基础「二」复合 ...
- Node.js「四」—— 路由 / EJS 模板引擎 / GET 和 POST
本文为 Node.js 系列笔记第四篇.文章参考:nodejs 教程:<深入浅出 Node.js>:阮一峰 nodejs 博客: Node.js v16.13.0 文档 文章目录 一.路由 ...
- 云原生系列「四」我为啥不看好ServiceMesh?
前言 今年,ServiceMesh(服务网格)概念在社区里头非常火,有人提出2018年是ServiceMesh年,还有人提出ServiceMesh是下一代的微服务架构基础.作为架构师,如果你现在还不了 ...
- Vue「四」—— 组件生命周期、数据共享
Vue 系列笔记第四篇.本文参考:>> 黑马程序员 Vue 全套视频教程 Vue 系列文章
- 新手必备pr 2021快速入门教程「四」新建序列及参数设置
PR2021快速入门教程,学完之后,制作抖音视频,vlog,电影混剪,日常记录等不在话下!零基础,欢迎入坑! 本节内容 新建序列功能是Premiere中的一个常用功能,目的是为了确定视频的尺寸和帧率质 ...
- camunda流程引擎如此简单「四」
监听器的使用 EL表达式:${} Camunda BPM支持统一表达语言(EL),它是JSP 2.1标准(JSR-245)的一部分.因此,它使用开源的JUEL实现.要获得有关表达式语言用法的更多常规信 ...
最新文章
- html css 极简模板,极简主义作品展示HTML模板
- openMP的一点使用经验 四
- JQuery图片无限循环滚动源码
- Java Zip压缩实现(亲测)
- java sox语音_Sox语音转换的相关知识
- net程序员的iPhone开发-MonoTouch
- “XEIM”国内开源即时通讯XEIM
- 高职计算机期末质量分析,利用SPASS进行计算机基础考试试卷质量分析
- 运营商数据治理实践-郭岳
- Java 实验5 T5
- 区块链软件:区块链的迅猛发展
- 目录启动CXF启动报告LinkageError异常以及Java的endorsed机制
- 开课吧Java课堂之动态方法调度
- POJ 2773 Happy 2006 【数论,容斥原理+二分】
- (日常搬砖)python3.7内置调试器PDB
- c语言单片机实验报告,本科单片机c语言实验手册(实验报告).doc
- mysql存储图片特征向量_图像特征提取之(一)HOG特征
- R语言使用aggregate函数和median函数计算每个分组数据的中位数
- C++ 模板中的类型获取(一)
- 怎么申请企业邮箱,企业邮箱快速登录入口
热门文章
- pic12f508c语言程序,PIC烧写器(QL-PIC280编程器)
- struts2中验证码的生成和使用
- 医药之家:政策频出!儿童药研发迎良机
- 为什么移动的4G频段会那么高?
- android studio全局查找替换,android-studio
- VMware中chrome、Edge浏览器透明菜单、白菜单 及 复制虚拟机互相踢、冲突问题解决
- 餐饮厨具设备公司官网织梦模板
- [附源码]计算机毕业设计大学生心理测评系统Springboot程序
- Qt程序启动时报错0xc000007b解决办法
- server使用abp中调用存储过程 sql_ASP调用sql server 存储过程详解-附带实例-