当前位置: 首页 > article >正文

Kotlin 2.1.0 入门教程(十)if、when

if 表达式

if 是一个表达式,它会返回一个值。

不存在三元运算符(condition ? then : else),因为 if 在这种场景下完全可以胜任。

var max = aif (a < b) max = bif (a > b) {max = a
} else {max = b
}max = if (a > b) a else bval maxLimit = 1val maxOrLimit = if (maxLimit > a) maxLimit else 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 是一种基于多个可能的值或条件运行代码的条件表达式。它类似于 JavaC 等语言中的 switch 语句。

val x = 2when (x) {1 -> print("x == 1")2 -> print("x == 2")else -> print("x is neither 1 nor 2")
}

when 会依次将它的参数与所有分支的条件进行匹配,直到某个分支的条件被满足为止。

你可以以几种不同的方式使用 when。首先,你可以将 when 用作表达式或语句。作为表达式,when 会返回一个值,供你在代码中后续使用。作为语句,when 用于完成某个操作,而不会返回任何进一步使用的值。

// 表达式。
// 返回一个字符串,该字符串被赋值给变量 text。
val text = when (x) {1 -> "x == 1"2 -> "x == 2"else -> "x is neither 1 nor 2"
}
// 语句。
// 不返回任何值,但会触发一个打印语句。
when (x) {1 -> print("x == 1")2 -> print("x == 2")else -> print("x is neither 1 nor 2")
}

可以使用带有或不带有对象的 when。无论是否在 when 中使用对象,表达式或语句的行为都是相同的。我们建议在可能的情况下使用带有对象的 when,因为它清晰地展示你在检查什么,使你的代码更易于阅读和维护。

// 带对象。
when (x) { ... }
// 不带对象。
when { ... }

根据你如何使用 when,对于是否需要在分支中覆盖所有可能的情况有不同的要求。

如果你将 when 用作语句,你不需要覆盖所有可能的情况。在下面的例子中,并没有覆盖所有情况,因此当不匹配任何分支时,不会发生任何事情。但也不会出现错误:

val x = 3
when (x) {// 并未覆盖所有情况。1 -> print("x == 1")2 -> print("x == 2")
}

when 语句中,各个分支的值会被忽略。就像 if 一样,每个分支可以是一个代码块,而代码块的值是块中最后一个表达式的值。

如果你将 when 用作表达式,那么你必须覆盖所有可能的情况,也就是说,它必须是穷尽的。第一个匹配分支的值将成为整个表达式的值。如果你没有覆盖所有情况,编译器会报错。

如果你的 when 表达式有一个对象,你可以使用 else 分支来确保覆盖所有可能的情况,但这并不是强制性的。例如,如果对象是一个布尔类型、枚举类、密封类,或者它们的可空类型,那么你可以不使用 else 分支来覆盖所有情况。例如:

enum class Bit {ZERO, ONE
}val numericValue = when (getRandomBit()) {// 不需要 else 分支,因为所有可能的情况都已经被覆盖了。Bit.ZERO -> 0Bit.ONE -> 1
}

如果你的 when 表达式没有对象,那么你必须有一个 else 分支,否则编译器会报错。当没有其他分支条件被满足时,else 分支会被执行。例如:

val number = 5val result = when {number > 0 -> "Positive"number < 0 -> "Negative"// 必须有 else 分支,因为没有对象。else -> "Zero" 
}

when 表达式和语句提供了多种方法来简化代码、处理多个条件以及执行类型检查。
你可以通过在单行中用逗号分隔多个条件,为多个案例定义共同的行为。例如:

val x = 2when (x) {1, 2, 3 -> println("x is 1, 2, or 3")4, 5, 6 -> println("x is 4, 5, or 6")else -> println("x is not in the range 1 to 6")
}

你可以使用任意表达式(不仅仅是常量)作为分支条件。例如:

val x = 5
val y = 10when (x) {y -> println("x is equal to y")y + 5 -> println("x is equal to y + 5")y - 5 -> println("x is equal to y - 5")else -> println("x is not equal to y, y + 5, or y - 5")
}

在这个例子中,yy + 5y - 5 都是作为分支条件的表达式。when 会根据 x 的值与这些表达式的结果进行比较,从而选择对应的分支。这种方式使得 when 的条件更加灵活,可以用于更复杂的逻辑判断。

你还可以通过 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 链的替代品。如果没有对象,分支条件就是布尔表达式。第一个条件为 true 的分支会被执行:

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

你可以通过以下语法在变量中捕获对象:

fun Request.getBody() =when (val response = executeRequest()) {is Success -> response.bodyis HttpError -> throw HttpException(response.status)}

when 表达式或语句的主体中引入的变量的作用域仅限于该 when 表达式或语句的内部。

when 表达式中的守护条件

守护条件是一个实验性功能,可能会随时发生变化。

守护条件允许你在 when 表达式的分支中包含多个条件,从而使复杂的控制流程更加明确和简洁。你可以在带有对象的 when 表达式或语句中使用守护条件。

要在分支中包含守护条件,请将其放在主条件之后,并用 if 分隔。

sealed interface Animal {data class Cat(val mouseHunter: Boolean) : Animaldata class Dog(val breed: String) : Animal
}fun feedAnimal(animal: Animal) {when (animal) {is Animal.Dog -> feedDog()is Animal.Cat if !animal.mouseHunter -> feedCat()else -> println("Unknown animal")}
}

在一个 when 表达式中,你可以同时使用带有守护条件和没有守护条件的分支。带有守护条件的分支中的代码只有在主条件和守护条件都为 true 时才会执行。如果主条件不满足,守护条件不会被评估。

如果你在没有 else 分支的 when 语句中使用守护条件,并且没有任何条件匹配,那么没有任何分支会被执行。

否则,如果你在没有 else 分支的 when 表达式中使用守护条件,编译器会要求你声明所有可能的情况,以避免运行时错误。

此外,守护条件还支持 else if 的功能。

when (animal) {// 检查 animal 是否是 Dog。is Animal.Dog -> feedDog()// 检查 animal 是否是 Cat 并且不是 mouseHunter。is Animal.Cat if !animal.mouseHunter -> feedCat()// 如果前面的条件都不匹配,并且 animal.eatsPlants 为 true,则此。else if animal.eatsPlants -> giveLettuce()// 如果前面的条件都不匹配,则此。else -> println("Unknown animal")
}

你可以在一个分支中通过使用布尔运算符 &&|| 组合多个守护条件。为了避免混淆,请使用括号将布尔表达式括起来。

when (animal) {is Animal.Cat if (!animal.mouseHunter && animal.hungry) -> feedCat()
}

你可以在任何带有对象的 when 表达式或语句中使用守护条件,但有一个例外,当你的条件是通过逗号分隔的多个值时,例如 0, 1 -> print("x == 0 or x == 1"),这种情况下不能使用守护条件。

要在命令行界面中启用守护条件,运行以下命令:

kotlinc -Xwhen-guards main.kt

要在 Gradle 中启用守护条件,将以下代码添加到 build.gradle.kts 文件中:

kotlin {compilerOptions {freeCompilerArgs.add("-Xwhen-guards")}
}

相关文章:

Kotlin 2.1.0 入门教程(十)if、when

if 表达式 if 是一个表达式&#xff0c;它会返回一个值。 不存在三元运算符&#xff08;condition ? then : else&#xff09;&#xff0c;因为 if 在这种场景下完全可以胜任。 var max aif (a < b) max bif (a > b) {max a } else {max b }max if (a > b) a…...

编程式路由

<script> export default {name: video-Info1,created () {setTimeout(() > {this.$router.push({ name: home })}, 3000)} } </script> 编程式路由&#xff1a;实现 不需要用户点击router-link&#xff0c;由代码实现路由跳转。 应用场景&#xff1a;用户登录…...

openAI官方prompt技巧(一)

1. 使用最新的模型 2. 将指令放在提示词的开头&#xff0c;并使用 ### 或 """ 来分隔指令和上下文&#xff0c;例如 错误示范❌ 将下面的文本总结为一个要点列表&#xff0c;列出最重要的内容。 Summarize the text below as a bullet point list of the most…...

利用 Python 爬虫获取按关键字搜索淘宝商品的完整指南

在电商数据分析和市场研究中&#xff0c;获取商品的详细信息是至关重要的一步。淘宝作为中国最大的电商平台之一&#xff0c;提供了丰富的商品数据。通过 Python 爬虫技术&#xff0c;我们可以高效地获取按关键字搜索的淘宝商品信息。本文将详细介绍如何利用 Python 爬虫技术获…...

LeetCode 0080.删除有序数组中的重复项 II:双指针 - C++/Java5 行版

【LetMeFly】80.删除有序数组中的重复项 II&#xff1a;双指针 - C/Java5 行版 力扣题目链接&#xff1a;https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/ 给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超…...

【C++高并发服务器WebServer】-15:poll、epoll详解及实现

本文目录 一、poll二、epoll2.1 相对poll和select的优点2.2 epoll的api2.3 epoll的demo实现2.5 epoll的工作模式 一、poll poll是对select的一个改进&#xff0c;我们先来看看select的缺点。 我们来看看poll的实现。 struct pollfd {int fd; /* 委托内核检测的文件描述符 */s…...

MapReduce是什么?

MapReduce 是一种编程模型&#xff0c;最初由 Google 提出&#xff0c;旨在处理大规模数据集。它是分布式计算的一个重要概念&#xff0c;通常用于处理海量数据并进行并行计算。MapReduce的基本思想是将计算任务分解为两个阶段&#xff1a;Map 阶段和 Reduce 阶段。 Map 阶段&a…...

git提交到GitHub问题汇总

1.main->master git默认主分支是maser&#xff0c;如果是按照这个分支名push&#xff0c;GitHub会出现两个branch&#xff0c;与预期不符 解决方案&#xff1a;更改原始主分支名为main git config --global init.defaultBranch main2.git&#xff1a;OpenSSL SSL_read: SS…...

CNN-GRU卷积神经网络门控循环单元多变量多步预测,光伏功率预测(Matlab完整源码和数据)

代码地址&#xff1a;CNN-GRU卷积神经网络门控循环单元多变量多步预测&#xff0c;光伏功率预测&#xff08;Matlab完整源码和数据) CNN-GRU卷积神经网络门控循环单元多变量多步预测&#xff0c;光伏功率预测 一、引言 1.1、研究背景和意义 随着全球能源危机和环境问题的日…...

编译原理面试问答

编译原理面试拷打 1.编译原理的基本概念 编译原理是研究如何将高级程序语言转换为计算机可执行代码的理论与技术&#xff0c;其核心目标是实现高效、正确的代码翻译。 **编译器&#xff1a;**将源代码转化为目标代码&#xff08;机器码、字节码等&#xff09;。一次翻译整个程…...

LIMO:上海交大的工作 “少即是多” LLM 推理

25年2月来自上海交大、SII 和 GAIR 的论文“LIMO: Less is More for Reasoning”。 一个挑战是在大语言模型&#xff08;LLM&#xff09;中的复杂推理。虽然传统观点认为复杂的推理任务需要大量的训练数据&#xff08;通常超过 100,000 个示例&#xff09;&#xff0c;但本文展…...

Java 魔法:精准掌控 PDF 合同模板,指定页码与关键字替换签章日期

朋友们&#xff01;在实际业务场景中&#xff0c;经常会碰到处理 PDF 合同模板的需求&#xff0c;要在几十页的合同里对指定页面替换公章、签名和日期&#xff0c;还涉及多人签名以及多个公司盖公章。下面就给大家分享两种用 Java 处理这类问题的方法&#xff0c;一种是通过指定…...

Ollama 部署本地大语言模型

一、下载安装ollama 1.百度 ollama Ollama 2.点击下载 可以复制下载链接&#xff0c;使用下载器下载。 3.双击安装 默认安装目录&#xff1a;C:\Users\用户名\AppData\Local\Programs\Ollama 二、更改模型下载目录 0.默认下载目录 (跳过) 之前没下载过模型&#xff0c;不…...

Jackson扁平化处理对象

POJO对象 Data public class People {private PeopleInfo peopleInfo;private List<String> peopleIds;private Map<String, String> peopleMap;Datapublic static class PeopleInfo {private String name;private String address;} }JSON序列化处理 直接将对象进…...

在 Ubuntu 上安装 MySQL 的详细指南

在Ubuntu环境中安装 mysql-server 以及 MySQL 开发包&#xff08;包括头文件和动态库文件&#xff09;&#xff0c;并处理最新版本MySQL初始自动生成的用户名和密码&#xff0c;可以通过官方的APT包管理器轻松完成。以下是详细的步骤指南&#xff0c;包括从官方仓库和MySQL官方…...

pytest-xdist 进行多进程并发测试!

在软件开发过程中&#xff0c;测试是确保代码质量和可靠性的关键步骤。随着项目规模的扩大和复杂性的增加&#xff0c;测试用例的执行效率变得尤为重要。为了加速测试过程&#xff0c;特别是对于一些可以并行执行的测试用 例&#xff0c;pytest-xdist 提供了一种强大的工具&…...

24.ppt:小李-图书策划方案【1】

目录 NO1234​ NO5678​ NO1234 新建PPT两种方式&#x1f447;docx中视图→导航窗格→标题1/2/3ppt新建幻灯片→从大纲→重置开始→版式设计→主题插入→表格 NO5678 SmartArt演示方案&#xff1a;幻灯片放映→自定义幻灯片放映→新建→选中添加...

模型 替身决策

系列文章分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。替身决策&#xff0c;换位思考&#xff0c;多角度决策。 1 替身决策模型的应用 1.1 替身决策模型在面试中的应用-小李的求职面试 小李是一名应届毕业生&#xff0c;正在积极寻找工作机会。在面试过程中…...

ESP32S3读取数字麦克风INMP441的音频数据

ESP32S3 与 INMP441 麦克风模块的集成通常涉及使用 I2S 接口进行数字音频数据的传输。INMP441 是一款高性能的数字麦克风&#xff0c;它通过 I2S 接口输出音频数据。在 Arduino 环境中&#xff0c;ESP32S3 的开发通常使用 ESP-IDF&#xff08;Espressif IoT Development Framew…...

docker环境下部署face-search开源人脸识别模型

由于我们是直接将face-search部署在docker容器中的,所以,在部署之前一定要检查一下自己的docker环境,要不然部署过程中会出现各种各样的问题 我这里的docker环境是 一、安装docker环境 如果docker版本比较低或者docker-compose的版本比较低的情况下,部署的时候docker的yml…...

301.华为交换机堆叠技术基础

华为交换机堆叠技术基础 一、概念及原理部分1.堆叠简介1.1 什么是堆叠1.2 可靠性网络架构1.3 华为堆叠设备1.4 其他厂商的堆叠2.堆叠的示意图3.堆叠的应用3.1 中小企业3.2 园区网4.堆叠的原理4.1基本的概念4.2 堆叠建立4.3 角色选举4.4 版本同步4.5 配置同步4.6 堆叠系统的登录…...

【数据库创建】用ij工具部署Derby数据库并验证

Java有一个内置的Derby数据库&#xff0c;是一个完全用Java语言编写的、功能强大的微型数据库&#xff0c;其基础引擎和内嵌的JDBC驱动总共大约2MB大小。Derby为用户提供了轻量的标准数据库引擎&#xff0c;它可以紧密地嵌入到任何基于Java的解决方案中。 Derby的特性令人惊奇&…...

飞牛fnOS安装了Airplay没有声音找不到声卡的问题

主要问题描述&#xff1a;我在飞牛的Docker里安装了 Airplay&#xff0c; 这样把NAS接一个外接音箱&#xff0c;就可以当成无线音箱来用&#xff0c;直接把手机的音乐播放投到上面来播放。 &#xff08;文章底部有写我是怎么安装Airplay的&#xff09; 我的报错如下&#xff1…...

netcore openTelemetry+prometheus+grafana

一、netcore项目 二、openTelemetry 三、prometheus 四、grafana添加Dashborad aspire/src/Grafana/dashboards at main dotnet/aspire GitHub 导入&#xff1a;aspnetcore.json和aspnetcore-endpoint.json 效果&#xff1a;...

全程Kali linux---CTFshow misc入门(38-50)

第三十八题&#xff1a; ctfshow{48b722b570c603ef58cc0b83bbf7680d} 第三十九题&#xff1a; 37换成1&#xff0c;36换成0&#xff0c;就得到长度为287的二进制字符串&#xff0c;因为不能被8整除所以&#xff0c;考虑每7位转换一个字符&#xff0c;得到flag。 ctfshow{5281…...

DeepSeek与人工智能的结合:探索搜索技术的未来

云边有个稻草人-CSDN博客 目录 引言 一、DeepSeek的技术背景 1.1 传统搜索引擎的局限性 1.2 深度学习在搜索中的优势 二、DeepSeek与人工智能的结合 2.1 自然语言处理&#xff08;NLP&#xff09; 示例代码&#xff1a;基于BERT的语义搜索 2.2 多模态搜索 示例代码&…...

用 DeepSeek + Kimi 自动做 PPT,效率起飞

以下是使用 DeepSeek Kimi 自动做 PPT 的详细操作步骤&#xff1a; 利用 DeepSeek 生成 PPT 内容&#xff1a; 访问 DeepSeek 官网&#xff0c;完成注册/登录后进入对话界面。输入指令&#xff0c;例如“请用 Markdown 格式生成一份关于[具体主题]的 PPT 大纲&#xff0c;需包…...

LeetCode 每日一题 2025/2/3-2025/2/9

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 2/3 680. 验证回文串 II2/4 922. 按奇偶排序数组 II2/5 90. 子集 II2/6 47. 全排列 II2/7 59. 螺旋矩阵 II2/8 63. 不同路径 II2/9 80. 删除有序数组中的重复项 II 2/3 680…...

自动驾驶数据集三剑客:nuScenes、nuImages 与 nuPlan 的技术矩阵与生态协同

目录 1、引言 2、主要内容 2.1、定位对比&#xff1a;感知与规划的全维覆盖 2.2、数据与技术特性对比 2.3、技术协同&#xff1a;构建全栈研发生态 2.4、应用场景与评估体系 2.5、总结与展望 3、参考文献 1、引言 随着自动驾驶技术向全栈化迈进&#xff0c;Motional 团…...

设计模式 ->模板方法模式(Template Method Pattern)

模板方法模式 模板方法模式是一种行为设计模式&#xff0c;它在一个方法中定义一个操作的算法骨架&#xff0c;而将一些步骤延迟到子类中实现。它允许子类在不改变算法结构的情况下重新定义算法中的某些步骤 特点 算法骨架&#xff1a; 在基类中定义算法的框架延迟实现&…...