快速入门Kotlin②控制流函数

控制流

if

if是一个表达式,可以用于条件判断和控制流。

fun main() {// 传统用法val a = 1val b = 2var max = aif (a < b) max = b// With elsevar max2: Intif (a > b) {max2 = a} else {max2 = b}// 作为表达式val max3 = if (a > b) a else b
}

when

when 表达式取代了Java 的 switch 语句,可以用任意表达式(而不只是常量,比如in/is/函数)作为分支条件。

fun main() {val obj: Any  = ""val result = when (obj) {1          -> "One"//假如很多分支需要用相同的方式处理,则可以把多个分支条件放在一起2, 3       -> "Two or three""Hello"    -> "Greeting"//任意表达式(而不只是常量)作为分支条件(in/is/函数)is Long    -> "Long"!is String -> "Not a string"else       -> "Unknown"}
}

for

for 循环可以对任何提供迭代器(iterator)的对象进行遍历。

fun main() {val list = listOf("apple", "banana", "otherfruit")for (item in list) {println(item)}//通过索引遍历一个数组或者一个 listfor (index in list.indices) {println("item at $index is ${list[index]}")}//区间表达式for (i in 1..3) {println(i)}for (i in 6 downTo 0 step 2) {println(i)}
}

while

whiledo..while 照常使用。

fun main() {//while 与 do..while 照常使用val list = listOf("apple", "banana", "otherfruit")var index = 0while (index < list.size) {println("item at $index is ${list[index]}")index++}index = 0do {println("item at $index is ${list[index]}")index++}while (index < list.size)
}

返回和跳转

Kotlin 有三种结构化跳转表达式:return、break和continue。

  • return。默认从最直接包围它的函数或者匿名函数返回。

  • break。终止最直接包围它的循环。

  • continue。继续下一次最直接包围它的循环。

fun main() {findNumberByReturn(3)forByBreak();forByContinue()
}fun findNumberByReturn(target: Int): Boolean {val numbers = listOf(1, 2, 3, 4, 5)for (number in numbers) {if (target == number) {return true // 结束函数并返回找到的值}println(number)}return false  // 循环结束后未找到目标值,返回 -1
}fun forByBreak() {val numbers = listOf(1, 2, 3, 4, 5)for (number in numbers) {if (number == 3) {break  // 循环终止}println(number)}//输出:1 2
}fun forByContinue() {val numbers = listOf(1, 2, 3, 4, 5)for (number in numbers) {if (number == 3) {continue  // 跳过当前迭代,继续下一次迭代}println(number)}//输出:1 2 4 5
}

函数

参数

参数:函数参数定义 name: type。参数用逗号隔开,每个参数必须有显式类型。 默认参数 :函数参数可以有默认值,当省略相应的参数时使用默认值。 具名参数:具名参数是一种在函数调用时指定参数名称的方式。在函数调用时使用 参数名 = 值 的形式来传递参数。

可变参数:可以用 vararg 修饰符标记,通常是最后一个参数。允许将可变数量的参数传递给函数。 默认参数特殊Case:如果在默认参数之后的最后一个参数是 lambda 表达式,那么它既可以作为具名参数在括号内传入,也可以在括号外传入。

fun main() {println(getResult(2, 3)) //输出:6//默认参数println(getResult(2)) //输出:2//具名参数foo(baz = 1) // 输出:bar is 0, baz is 1//可变参数println(asList(1, 2, 3)) //输出:[1, 2, 3]
}// Kotlin 中的函数使用 fun 关键字声明。
fun getResult(x: Int, y: Int = 1) : Int {return x * y
}//具名参数举例
fun foo(bar: Int = 0,baz: Int,
) {println("bar is $bar, baz is $baz")
}fun<T> asList(vararg ts: T): List<T> {val result = ArrayList<T>()for (t in ts) {result.add(t)}return result
}

返回类型

具有块代码体的函数必须始终显式指定返回类型,除非他们旨在返回 Unit。因为这样的函数在代码体中可能有复杂的控制流,并且返回类型对于读者(有时甚至对于编译器)是不明显的。

函数作用域&类型

1. 顶层函数,无需创建类来保存函数。

2. 局部作用域:嵌套函数。

3. 成员函数:在类或对象内部定义的函数。

4. 扩展函数:可以在不继承或修改类的情况下,为类添加额外的行为和功能。扩展函数是静态解析的,它并没有对类进行实际的修改或继承。扩展函数的作用域仅限于定义它的文件内。

5. 泛型函数:可以在函数中使用类型参数的特殊函数,它增加了函数的灵活性和重用性。

//顶层函数,无需创建类来保存函数。
fun main() {Sample().foo() // 创建类 Sample 实例并调用 foo,输出:FooouterFunction() // 嵌套函数。输出:Outer function Nested functionval str = "hello"println(str.reverseStr()) //输出:ollehprintln(createList("apple", "banana", "orange")) //输出:[apple, banana, orange]println(createList(1, 2, 3, 4, 5)) //输出:[1, 2, 3, 4, 5]
}class Sample {//成员函数:类或对象内部定义的函数。fun foo() { println("Foo") }
}fun outerFunction() {println("Outer function")//嵌套函数:可以在外部函数内部进行封装,并且只在外部函数内部可见和使用。fun nestedFunction() {println("Nested function")}nestedFunction()
}// 扩展函数:将字符串反转
fun String.reverseStr(): String {return this.reversed()
}//泛型函数: `createList` 是一个泛型函数,它接受可变数量的参数 `items`,类型为 `T`。函数的返回类型为 `List<T>`,即根据传递的参数类型返回相应类型的列表。
fun <T> createList(vararg items: T) : List<T> {return items.toList()
}

高阶函数和lambda 表达式

高阶函数

是将函数用作参数或返回值的函数,更加灵活。

  • map: 函数用于对集合中的每个元素应用给定的转换函数,并返回新集合。

  • filter:函数用于根据给定的条件函数过滤集合中的元素,返回新集合。

  • forEach: 函数用于对集合中的每个元素应用给定的操作函数,没有返回值。

fun main() {val numbers = listOf(1, 2, 3, 4, 5)val convertNumbers = numbers.map { it * it }val evenNumbers = numbers.filter { it % 2 == 0 }println(convertNumbers) //输出:[1, 4, 9, 16, 25]println(evenNumbers) //输出:[2, 4]numbers.forEach { print(it) } //输出:12345
}

函数类型

函数类型声明指定了函数参数和返回值的类型,以及函数的参数个数和参数类型。语法如下:

(parameters) -> returnType

  • parameters 是函数的参数列表,可以包含零个或多个参数,在声明中使用参数名和类型来指定。

  • returnType 是函数的返回值类型,用于指定函数的返回结果类型。

常见的函数类型声明如下:

//不带参数的函数类型
() -> Unit
//带有一个整数参数的函数类型
(Int) -> Unit
//带有两个字符串参数和一个整数返回值的函数类型
(String, String) -> Int
//带有一个整数参数和一个字符串返回值的函数类型
(Int) -> String

代码示例:

fun main() {applyFunction(::square) //输出结果 result: 1764
}/*** applyFunction 是一个高阶函数,它接受一个函数类型参数 function。* applyFunction 函数内部调用传递的函数类型参数,并将结果打印出来。*/
fun applyFunction(function: (Int) -> Int) {val result = function(42)println("result: $result")
}/*** 我们将 square 函数作为参数传递给 applyFunction 函数。*/
fun square(x :Int) : Int {return x * x
}

Lambda 表达式

Lambda 表达式可以理解为轻量级的函数字面量,提供更简洁的语法。

基本语法如下:

val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
  • lambda 表达式总是括在花括号中。

  • 完整语法形式的参数声明放在花括号内,并有可选的类型标注。

  • 函数体跟在一个 -> 之后。

  • 如果推断出的该 lambda 的返回类型不是 Unit,那么该 lambda 主体中的最后一个(或可能是单个)表达式会视为返回值。

可以优化为:

val sum = { x: Int, y: Int -> x + y }

代码示例:

fun main() {//Lambda 表达式没有参数//定义了一个没有参数的 Lambda 表达式,并将其赋值给类型为 () -> Unit 的变量 greet。val great = { println("hello, kotlin") }great()  //输出:hello, kotlin//Lambda 表达式带有一个整数参数//定义了一个带有一个整数参数的 Lambda 表达式,并将其赋值给类型为 (Int) -> Int 的变量 squareval square: (Int) -> Int = { y -> y * y }println(square(5))  //输出:25//Lambda 表达式带有多个参数//定义了一个带有两个整数参数的 Lambda 表达式,并将其赋值给类型为 (Int, Int) -> Int 的变量 add。val add = { x: Int, y: Int -> x + y }println(add(3, 7))  //输出:10//亦或者写为:val add1: (Int, Int) -> Int = { x, y -> x + y }println(add1(3, 7))  //输出:10
}

最后一个参数是 Lambda 表达式:可以使用末尾 Lambda 表达式的语法糖。这种语法糖允许我们在调用函数时将 Lambda 表达式放在圆括号外部,增强了代码的可读性。

fun performOperation(value: Int, operation: (Int) -> Int): Int {return operation(value)
}fun main() {val result = performOperation(5) { number ->number * 2}println("Result: $result") //输出:Result: 10
}

匿名函数

Lambda表达式通常比匿名函数更简洁。但匿名函数在某些情况下可能更适合,比如需要显式指定返回类型或需要包含多个语句的情况。

基本语法:

fun(x: Int, y: Int): Int {return x + y
}//可以优化为:
//显式指定返回值为Int
fun(x: Int, y: Int): Int = x + y

代码示例:

fun main() {val numbers = listOf(1, 2, 3, 4, 5)// 匿名函数接受一个整数参数 num,并在函数体中定义了两个语句。// 首先,我们计算出 isEven 变量,表示数字是否为偶数。// 然后,我们返回一个布尔值,判断数字既是偶数又大于 2。// 通过使用匿名函数,我们可以在函数体中包含多个语句,更好地处理复杂的过滤逻辑。// fun(num) : Boolean显式指定了返回类型Boolean;多条语句情况下匿名函数语义更清晰val filteredNumbersAnonymous = numbers.filter (fun(num) : Boolean {val isEven = num % 2 == 0return isEven && num > 2})// Lambda 表达式的函数体与匿名函数相同,包含了多个语句。// Lambda 表达式的语法更为简洁,但在这种情况下,匿名函数的定义也相对清晰。val filteredNumbersLambda = numbers.filter { num ->val isEven = num % 2 == 0isEven && num >2}println("Filtered numbers: $filteredNumbersAnonymous") //输出:Filtered numbers: [4]println("Filtered numbers: $filteredNumbersLambda") //输出:Filtered numbers: [4]
}

内联函数

当一个函数被声明为 inline 时,编译器会在调用该函数的地方将函数的实际代码复制到调用处,而不是通过函数调用的方式进行执行。

优点:

  • 减少函数调用的开销:函数调用会涉及到栈帧的创建、参数传递等操作,而通过函数内联可以避免这些开销,提高代码的执行效率。

缺点:

  • 不宜过度使用,可能会导致代码膨胀:内联函数的复制会增加代码的大小,因此在频繁调用的小函数上使用 inline 可能会导致代码膨胀,影响包的大小和性能。

  • 不可内联的情况:某些情况下,编译器无法进行函数内联,例如递归函数、函数体包含函数表达式、函数参数被函数引用等。

代码举例:

//我们定义了一个名为 measureTime 的 inline 函数。该函数接受一个函数类型的参数 execute
inline fun measureTime(execute: () -> Unit) {//函数体内部,我们记录了开始时间,执行了传递的代码块 block,然后记录了结束时间,并打印出代码块的执行时间。val startTime = System.currentTimeMillis()execute()val endTime = System.currentTimeMillis()println("Execution time: ${endTime - startTime} milliseconds")//输出:Execution time: 1005 milliseconds
}fun main() {//编译时会将函数调用处的代码块直接替换到函数体内部,而不会创建额外的函数调用。这样可以减少函数调用的开销,并且在一些情况下可以提高性能。measureTime {// 执行一些耗时的操作Thread.sleep(1000)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/766367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯刷题_day2

文章目录 DAY2杨辉三角查找整数数列特征字母图形(未通过全部样例) DAY2 杨辉三角 【题目描述】 杨辉三角形又称Pascal三角形&#xff0c;它的第i1行是(ab)i的展开式的系数。它的一个重要性质是&#xff1a;三角形中的每个数字等于它两肩上的数字相加。 下面给出了杨辉三角形的…

2024智能短信营销推广系统使用攻略

智能短信营销推广系统以其精准、高效的特点&#xff0c;成为企业与消费者建立联系的重要桥梁。云衔科技凭借其先进的技术和专业的服务&#xff0c;为企业提供了一套完善的智能短信营销推广系统解决方案&#xff0c;让企业在短时间内实现大规模、个性化的短信营销活动。 云衔科…

01---java面试八股文——mybatis-------10题

1、什么是MyBatis Mybatis是一个半ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;它内部封装了JDBC&#xff0c;开发时只需要关注SQL语句本身&#xff0c;不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql&#xff0c…

数据结构与集合(一)

当我们谈论数据结构时&#xff0c;我们实际上在讨论一种组织和管理数据的方式。数据结构是计算机科学中非常重要的一部分&#xff0c;它为我们提供了存储、检索和操作数据的方法。在数据结构中&#xff0c;链表是一种基本且常用的数据结构&#xff0c;它由一系列节点组成&#…

【Word自动化办公】使用python-docx对Word进行操作

目录 一、环境安装 二、文档各组成结构获取 2.1 组成结构讲解 2.2 段落run对象的切分标准 三、获取整篇文档内容 四、写入指定样式的数据 4.1 通过add_paragraph与add_run参数添加样式 4.2 单独设置文本样式 五、添加标题 六、换行符&换页符 七、添加图片数据 …

Go 版本 Etcd 客户端操作 Etcd(附完整 Demo)

Etcd 相关参考资料 Etcd 的介绍与使用&#xff1a;Etcd 介绍与使用&#xff08;入门篇&#xff09;-CSDN博客 Etcd Raft 协议&#xff1a;Etcd Raft 协议&#xff08;进阶篇&#xff09;-CSDN博客 本文诣在使用 Go 客户端操作 Etcd&#xff0c;并实现元数据的写入&#xff0…

迷宫(一)(DFS BFS)

//新生训练 #include <bits/stdc.h> using namespace std; int n, m; bool f; char mp[15][15]; int vis[15][15]; int dir[4][2] {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; bool in(int x, int y) {return 0 < x && x < n && 0 < y && y …

2.1-如何配置华三网络设备的远程登录?(ssh,telnet,https)

&#xff08;1&#xff09;华三网络设备远程登录的配置实验 1.实验目标 目标&#xff1a;实现远程ssh登录基本配置(http,https登录&#xff09; 要求&#xff1a;配置后&#xff0c;即可使用远程工具进行远程登录。 配置过程&#xff1a; 1.创建交换机的本地帐号。&#xff0…

NFT交易市场-后端开发

首先我们需要配置好我们的ipfs&#xff0c;参考官方文档 1.https://docs.ipfs.tech/install/command-line/#system-requirementshttps://docs.ipfs.tech/how-to/command-line-quick-start/#initialize-the-repository 首先新建一个文件夹 然后在终端输入npm init -y命令进行初…

深入理解Redis的Sentinel机制

Sentinel简述 Sentinel为了解决什么问题&#xff1f; Sentinel&#xff08;哨岗、哨兵&#xff09;是Redis的高可用性&#xff08;high availability&#xff09;解决方案。 我们知道Redis 的主从复制模式可以将主节点的数据改变同步给从节点&#xff0c;这样从节点就可以起…

docker 和K8S知识分享

docker知识&#xff1a; 比如写了个项目&#xff0c;并且在本地调试没有任务问题&#xff0c;这时候你想在另外一台电脑或者服务器运行&#xff0c;那么你需要在另外一台电脑或者服务器配置相同的软件&#xff0c;比如数据库&#xff0c;web服务器&#xff0c;必要的插件和库等…

吴恩达机器学习笔记 二十七 决策树中连续值特征的选择 回归树

还是猫狗分类的案例&#xff0c;假如再增加一个特征weight&#xff0c;该值是一个连续的值&#xff0c;如何在决策树中使用该特征&#xff1f; 如下图所示&#xff0c;尝试不同的阈值&#xff0c;如 weight<9 , 此时左边有四个样本&#xff0c;都为猫&#xff0c;右边有六个…

分布式搜索引擎ES-RestClient查询文档快速入门

RestClient查询文档快速入门 文章目录 RestClient查询文档快速入门1.1、match_all1.2、全文检索查询1.3、精确查询1.4、复合查询-boolean query1.5、排序和分页1.6、高亮&#xff08;解析查询高亮结果&#xff09; 1.1、match_all package cn.mannor.hotel;import org.apache.…

C#,图论与图算法,计算图(Graph)的岛(Island)数量的算法与源程序

1 孤岛数 给定一个布尔矩阵,求孤岛数。一组相连的1形成一个岛。例如,下面的矩阵包含5个岛: 在讨论问题之前,让我们先了解什么是连接组件。无向图的连通分量是一个子图,其中每两个顶点通过一条路径相互连接,并且不与子图外的其他顶点连接。 所有顶点相互连接的图只有一个…

备战蓝桥杯(前缀和、差分篇)

Acwing 562.壁画 题目大意&#xff1a; 墙壁为一行&#xff0c; n n n个格子&#xff0c;每个时刻开始&#xff0c;先涂染料&#xff0c;再崩坏&#xff0c;涂过染料的格子不会崩坏&#xff0c;并且涂格子只能涂相邻未涂过的。 解题思路&#xff1a; 因为是先涂染料&#xff…

Tomcat 下载以及安装

Tomcat安装及配置教程主要分为四步&#xff1a; 步骤一&#xff1a;首先确认自己是否已经安装JDK 1. cmd&#xff1a;查看java的版本 步骤二&#xff1a;下载安装Tomcat 1. 下载tomcat :Apache Tomcat - Welcome! 2. 选择对应的tomcat版本&#xff1a; 3. 进行安装&#…

Uibot6.0 (RPA财务机器人师资培训第3天 )财务招聘信息抓取机器人案例实战

训练网站&#xff1a;泓江科技 (lessonplan.cn)https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981(本博…

鸿蒙一次开发,多端部署(十四)一多开发实例(短信)

本章从系统预置的应用中&#xff0c;选择短信应用作为典型的案例&#xff0c;从页面开发和工程结构的角度&#xff0c;介绍"一多"的具体实践。系统的产品形态在不断丰富中&#xff0c;当前主要有默认设备和平板两种产品形态&#xff0c;本章的具体实践也将围绕这两种…

ALPHA开发板中CAN硬件图

一. 简介 前面文章学习了 IMX6ULL芯片的 CAN总线协议&#xff0c;CAN传输速率。 本文来搜索 ALPHA开发板中CAN硬件原理图&#xff0c;以及CAN设备节点信息。这里主要是CAN控制器的驱动&#xff0c;属于IMX6ULL芯片内部的驱动&#xff0c;NXP官方已经写好。 CAN控制器的驱动…

使用Python抓取抖音直播间数据的简易指南【第152篇—抓取数据】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 使用Python抓取抖音直播间数据的简易指南 说明&#xff1a;本文已脱敏&#xff0c;隐去地址…