Kotlin 第二天
Kotlin 编程基础
一、课程目标
1.掌握 Kotlin 的基本语法格式
2.掌握 Kotlin 中的变量
3.掌握 Kotlin 中的运算符、字符串
4.掌握 Kotlin 中的选择结构语句、循环结构语句
5.掌握 Kotlin 中的变量类型转换、空值处理
二、Kotlin 基本语法格式
1. 程序入口
在 Kotlin 中,程序的入口点是main
函数,它是程序开始执行的地方。就如同其他编程语言(如 Java、C 等)都有特定的程序入口一样。
kotlin
fun main() {
println("Hello, Kotlin!")
}
fun
:Kotlin 里用于定义函数的关键字。无论是普通函数、成员函数还是顶层函数,都用fun
声明。main
:作为程序入口,此函数名称固定。()
:表示函数的参数列表,这里main
函数无参数,所以括号为空。{}
:大括号内是函数体,包含函数要执行的具体代码。println("Hello, Kotlin!")
:println
是 Kotlin 标准库中用于向控制台输出一行文本的函数,此处输出的文本为"Hello, Kotlin!"
。
带参数的main
函数
Kotlin 的main
函数可接收命令行参数,参数类型为Array<String>
。
kotlin
fun main(args: Array<String>) {
for (arg in args) {
println(arg)
}
}
args: Array<String>
:表明main
函数接收一个字符串数组作为参数,数组存储从命令行传递给程序的参数。for (arg in args)
:for
循环遍历args
数组中的每个元素,将其赋值给变量arg
并打印。
2. 注释
注释在编程中至关重要,能帮助开发者理解代码功能和逻辑,方便代码维护与协作开发。Kotlin 支持单行注释和多行注释。
单行注释
使用双斜杠//
表示,从//
开始到本行结束的内容会被编译器忽略。
kotlin
// 这是一个单行注释
val message = "This is a message"
多行注释
使用/*
和*/
表示,它们之间的内容会被编译器忽略,可跨越多行。
kotlin
/*
这是一个多行注释
可以包含多行文本
用于对代码块进行详细的说明
*/
val number = 10
嵌套注释
Kotlin 不支持嵌套的多行注释,例如以下代码是错误的:
kotlin
/*
外层注释开始
/* 内层注释开始 */
外层注释结束
*/
3. 语句结尾
在 Kotlin 中,语句结尾的分号;
是可选的。一般情况下,可省略分号让代码更简洁。
kotlin
// 省略分号
val name = "John"
println(name)
// 也可以使用分号
val age = 30; println(age)
多数场景下,建议省略分号,遵循 Kotlin 的简洁风格。但一行中写多个语句时,需用分号分隔。
4. 包声明
和 Java 类似,Kotlin 用包(package)组织代码,包声明通常位于文件顶部。
kotlin
package com.example.kotlinapp
fun main() {
println("This is a Kotlin app in com.example.kotlinapp package.")
}
package com.example.kotlinapp
:声明该文件属于com.example.kotlinapp
包。包命名常遵循反向域名规则,以避免命名冲突。- 包声明有助于将相关的类、函数和其他代码组织在一起,便于管理和维护。
5. 导入语句
若要使用其他包中的类、函数或其他元素,需用import
语句导入。
kotlin
package com.example.kotlinapp
import java.util.Date
fun main() {
val currentDate = Date()
println("Current date: $currentDate")
}
import java.util.Date
:导入 Java 标准库中的Date
类,此后在当前文件中可直接使用Date
类,无需使用全限定名java.util.Date
。- Kotlin 支持导入特定包下的所有内容,使用
import packageName.*
,但不推荐,因为可能引发命名冲突 。
6. 函数定义
除main
函数外,Kotlin 还可定义其他函数,函数可以有参数和返回值。
kotlin
// 定义一个带有两个参数并返回Int类型结果的函数
fun add(a: Int, b: Int): Int {
return a + b
}
fun main() {
val result = add(3, 5)
println("The result of addition is: $result")
}
fun add(a: Int, b: Int): Int
:定义名为add
的函数,接收两个Int
类型参数a
和b
,返回Int
类型结果。return a + b
:函数体中用return
关键字返回a
和b
的和。- 在
main
函数中调用add
函数,将结果存于result
变量,最后打印出来。
三、Kotlin 中的变量
1. 变量声明
Kotlin 中使用val
和var
关键字来声明变量。
val
:用于声明不可变变量,类似于 Java 中的final
变量,一旦赋值就不能再修改。var
:用于声明可变变量,可以多次赋值。
kotlin
// 使用val声明不可变变量
val immutableVariable: Int = 10
// 以下代码会报错,因为immutableVariable是不可变的
// immutableVariable = 20
// 使用var声明可变变量
var mutableVariable: String = "Hello"
// 可以对可变变量重新赋值
mutableVariable = "World"
2. 类型推断
Kotlin 具有智能的类型推断功能,在声明变量时可以省略类型声明。
kotlin
// Kotlin会自动推断变量类型为Int
val number = 10
// 自动推断变量类型为String
var text = "Kotlin"
四、Kotlin 中的运算符
1. 算术运算符
算术运算符用于执行基本的数学运算,Kotlin 支持常见的加、减、乘、除、取模等运算。
kotlin
fun main() {
val a = 10
val b = 3
// 加法运算
val sum = a + b
println("a + b 的结果: $sum")
// 减法运算
val difference = a - b
println("a - b 的结果: $difference")
// 乘法运算
val product = a * b
println("a * b 的结果: $product")
// 除法运算
val quotient = a / b
println("a / b 的结果: $quotient")
// 取模运算(取余数)
val remainder = a % b
println("a % b 的结果: $remainder")
}
- 加法运算符(
+
) :用于计算两个数的和,如a + b
计算变量a
和b
的总和。 - 减法运算符(
-
) :用于计算两个数的差,即a - b
得到a
减去b
的结果。 - 乘法运算符(
\*
) :用于计算两个数的乘积,a * b
表示a
乘以b
。 - 除法运算符(
/
) :用于计算两个数的商,当两个操作数都是整数时,结果会向下取整。例如10 / 3
的结果是3
而不是3.333...
。 - 取模运算符(
%
) :用于计算两个数相除的余数,a % b
得到a
除以b
的余数。
2. 比较运算符
比较运算符用于比较两个值的大小或相等关系,其结果是布尔类型(true
或 false
)。
kotlin
fun main() {
val x = 5
val y = 8
// 等于比较
val isEqual = x == y
println("x 是否等于 y: $isEqual")
// 不等于比较
val isNotEqual = x != y
println("x 是否不等于 y: $isNotEqual")
// 大于比较
val isGreater = x > y
println("x 是否大于 y: $isGreater")
// 小于比较
val isLess = x < y
println("x 是否小于 y: $isLess")
// 大于等于比较
val isGreaterOrEqual = x >= y
println("x 是否大于等于 y: $isGreaterOrEqual")
// 小于等于比较
val isLessOrEqual = x <= y
println("x 是否小于等于 y: $isLessOrEqual")
}
- 等于运算符(
==
) :判断两个值是否相等,如果相等返回true
,否则返回false
。 - 不等于运算符(
!=
) :判断两个值是否不相等,若不相等返回true
,相等则返回false
。 - 大于运算符(
>
) :判断左边的值是否大于右边的值,满足条件返回true
,否则返回false
。 - 小于运算符(
<
) :判断左边的值是否小于右边的值,满足条件返回true
,否则返回false
。 - 大于等于运算符(
>=
) :判断左边的值是否大于或等于右边的值,满足条件返回true
,否则返回false
。 - 小于等于运算符(
<=
) :判断左边的值是否小于或等于右边的值,满足条件返回true
,否则返回false
。
3. 逻辑运算符
逻辑运算符用于组合布尔表达式,常用于条件判断中。
kotlin
fun main() {
val condition1 = true
val condition2 = false
// 逻辑与运算
val andResult = condition1 && condition2
println("condition1 && condition2 的结果: $andResult")
// 逻辑或运算
val orResult = condition1 || condition2
println("condition1 || condition2 的结果: $orResult")
// 逻辑非运算
val notResult = !condition1
println("!condition1 的结果: $notResult")
}
- 逻辑与运算符(
&&
) :只有当两个操作数都为true
时,结果才为true
,否则为false
。例如condition1 && condition2
中,因为condition2
为false
,所以结果为false
。 - 逻辑或运算符(
||
) :只要两个操作数中有一个为true
,结果就为true
,只有当两个操作数都为false
时,结果才为false
。如condition1 || condition2
中,由于condition1
为true
,所以结果为true
。 - 逻辑非运算符(
!
) :对一个布尔值取反,若操作数为true
,则结果为false
;若操作数为false
,则结果为true
。
4. 位运算符
位运算符用于对整数类型(如 Int
、Long
等)的二进制位进行操作。
kotlin
fun main() {
val num1 = 5 // 二进制表示: 0101
val num2 = 3 // 二进制表示: 0011
// 按位与运算
val bitwiseAnd = num1 and num2
println("num1 and num2 的结果: $bitwiseAnd")
// 按位或运算
val bitwiseOr = num1 or num2
println("num1 or num2 的结果: $bitwiseOr")
// 按位异或运算
val bitwiseXor = num1 xor num2
println("num1 xor num2 的结果: $bitwiseXor")
// 按位取反运算
val bitwiseNot = num1.inv()
println("num1 的按位取反结果: $bitwiseNot")
// 左移运算
val leftShift = num1 shl 2
println("num1 左移 2 位的结果: $leftShift")
// 右移运算
val rightShift = num1 shr 1
println("num1 右移 1 位的结果: $rightShift")
// 无符号右移运算
val unsignedRightShift = num1 ushr 1
println("num1 无符号右移 1 位的结果: $unsignedRightShift")
}
- 与运算符(
and
)**:对两个操作数的对应二进制位进行与运算,只有当对应位都为 1 时,结果位才为 1,否则为 0。 - 按位或运算符(
or
):对两个操作数的对应二进制位进行或运算,只要对应位中有一个为 1,结果位就为 1,只有当对应位都为 0 时,结果位才为 0。 - 按位异或运算符(
xor
):对两个操作数的对应二进制位进行异或运算,若对应位相同则结果位为 0,不同则结果位为 1。 - 按位取反运算符(
inv()
):对操作数的每个二进制位取反,即 0 变为 1,1 变为 0。 - 左移运算符(
shl
):将操作数的二进制位向左移动指定的位数,右边空出的位用 0 填充。左移 n 位相当于乘以 2 的 n 次方。 - 右移运算符(
shr
):将操作数的二进制位向右移动指定的位数,左边空出的位用符号位填充(正数补 0,负数补 1)。右移 n 位相当于除以 2 的 n 次方。 - 无符号右移运算符(
ushr
):将操作数的二进制位向右移动指定的位数,左边空出的位用 0 填充。
5. 赋值运算符
赋值运算符用于将一个值赋给变量,同时还支持复合赋值运算符。
kotlin
fun main() {
var num = 10
// 简单赋值
num = 20
println("简单赋值后 num 的值: $num")
// 加法赋值
num += 5
println("加法赋值后 num 的值: $num")
// 减法赋值
num -= 3
println("减法赋值后 num 的值: $num")
// 乘法赋值
num *= 2
println("乘法赋值后 num 的值: $num")
// 除法赋值
num /= 4
println("除法赋值后 num 的值: $num")
// 取模赋值
num %= 3
println("取模赋值后 num 的值: $num")
}
- 简单赋值运算符(
=
):将右边的值赋给左边的变量。 - 复合赋值运算符(
+=
、-=
、\*=
、/=
、%=
) :先进行相应的算术运算,再将结果赋给左边的变量。例如num += 5
相当于num = num + 5
。
6. 安全调用运算符和非空断言运算符
这两个运算符主要用于处理可空类型,增强代码的安全性。
kotlin
fun main() {
var nullableStr: String? = null
// 安全调用运算符
val length1 = nullableStr?.length
println("使用安全调用运算符获取长度: $length1")
nullableStr = "Hello"
val length2 = nullableStr?.length
println("使用安全调用运算符获取长度: $length2")
// 非空断言运算符
// nullableStr = null
// val length3 = nullableStr!!.length // 如果 nullableStr 为 null,会抛出空指针异常
val length4 = nullableStr!!.length
println("使用非空断言运算符获取长度: $length4")
}
- 安全调用运算符(
?.
) :用于在调用可空类型的属性或方法时避免空指针异常。如果可空类型的值为null
,则整个表达式返回null
,不会执行后续的属性或方法调用。 - 非空断言运算符(
!!
) :用于告诉编译器该可空类型的值一定不为null
。如果实际上该值为null
,则会抛出空指针异常。
7. Elvis 运算符
Elvis 运算符用于在可空类型的值为 null
时提供一个默认值。
kotlin
fun main() {
var nullableStr: String? = null
val result = nullableStr ?: "默认值"
println("使用 Elvis 运算符的结果: $result")
nullableStr = "Kotlin"
val result2 = nullableStr ?: "默认值"
println("使用 Elvis 运算符的结果: $result2")
}
Elvis 运算符(?:
)会先判断左边的可空类型的值是否为 null
,如果为 null
,则返回右边的默认值;如果不为 null
,则返回左边的值。
综上所述,Kotlin 中的运算符功能丰富,灵活运用这些运算符可以编写出高效、简洁的代码。在实际开发中,需要根据具体的需求选择合适的运算符。
五、Kotlin 中的字符串
在 Kotlin 中,字符串是一种非常常用的数据类型,用于表示文本信息。Kotlin 对字符串的处理提供了丰富的特性和便捷的操作方法,下面将详细讲解 Kotlin 中字符串的各个方面。
1. 字符串定义
在 Kotlin 里,可以使用双引号(""
)来定义字符串。字符串可以包含任意字符,包括字母、数字、标点符号等。
kotlin
// 定义一个简单的字符串
val simpleString = "Hello, Kotlin!"
// 定义一个包含特殊字符的字符串
val specialString = "This is a string with \"quotes\" and \nnew line."
val simpleString = "Hello, Kotlin!"
:使用双引号直接定义一个字符串,并将其赋值给变量simpleString
。val specialString = "This is a string with \"quotes\" and \nnew line."
:在字符串中,如果需要包含双引号("
),需要使用反斜杠(\
)进行转义;如果需要换行,可以使用转义字符\n
。
2. 字符串模板
Kotlin 支持字符串模板,这是一种非常方便的特性,允许在字符串中嵌入变量或表达式。使用 $
符号来引用变量,对于复杂的表达式,可以使用 ${}
。
kotlin
val name = "Alice"
// 使用字符串模板将变量 name 插入到字符串中
val greeting = "Hello, $name!"
println(greeting)
val num1 = 5
val num2 = 3
// 对于复杂的表达式,使用 ${}
val result = "两数之和: ${num1 + num2}"
println(result)
val greeting = "Hello, $name!"
:在字符串中使用$name
引用变量name
的值,当字符串被打印时,$name
会被替换为name
变量实际存储的值。val result = "两数之和: ${num1 + num2}"
:对于复杂的表达式,如num1 + num2
,需要使用${}
将表达式括起来,这样在字符串中就会计算表达式的值并插入到相应位置。
3. 原始字符串
Kotlin 提供了原始字符串的定义方式,使用三个双引号("""
)。原始字符串可以包含换行符和特殊字符,无需进行转义。
kotlin
val rawString = """
This is a raw string.
It can contain multiple lines
without using escape characters.
"Double quotes" don't need to be escaped.
"""
println(rawString)
val rawString = """ ... """
:使用三个双引号定义原始字符串,在这个字符串中,换行符和双引号等特殊字符都可以直接使用,无需进行转义。
4. 字符串方法
Kotlin 为字符串提供了许多实用的方法,用于对字符串进行各种操作,如获取长度、截取子字符串、转换大小写等。
4.1 获取字符串长度
kotlin
val str = "Kotlin Programming"
val length = str.length
println("字符串长度: $length")
val length = str.length
:通过length
属性获取字符串str
的长度,并将其赋值给变量length
。
4.2 截取子字符串
使用 substring
方法可以截取字符串的一部分。
kotlin
val str = "Kotlin Programming"
// 从索引 0 开始截取到索引 6(不包含索引 6)
val subStr = str.substring(0, 6)
println("截取的子字符串: $subStr")
val subStr = str.substring(0, 6)
:substring
方法接受两个参数,第一个参数是起始索引(包含),第二个参数是结束索引(不包含),这里从索引 0 开始截取到索引 6,得到的子字符串是"Kotlin"
。
4.3 转换大小写
可以使用 toUpperCase
和 toLowerCase
方法将字符串转换为大写或小写。
kotlin
val str = "Kotlin Programming"
// 将字符串转换为大写
val upperCaseStr = str.toUpperCase()
// 将字符串转换为小写
val lowerCaseStr = str.toLowerCase()
println("大写字符串: $upperCaseStr")
println("小写字符串: $lowerCaseStr")
val upperCaseStr = str.toUpperCase()
:调用toUpperCase
方法将字符串str
转换为大写形式。val lowerCaseStr = str.toLowerCase()
:调用toLowerCase
方法将字符串str
转换为小写形式。
4.4 字符串查找和替换
使用 indexOf
方法可以查找某个字符或子字符串在字符串中第一次出现的索引位置;使用 replace
方法可以替换字符串中的指定内容。
kotlin
val str = "Kotlin Programming"
// 查找 "Pro" 第一次出现的索引位置
val index = str.indexOf("Pro")
println("Pro 第一次出现的索引位置: $index")
// 将 "Kotlin" 替换为 "Java"
val replacedStr = str.replace("Kotlin", "Java")
println("替换后的字符串: $replacedStr")
val index = str.indexOf("Pro")
:indexOf
方法返回子字符串"Pro"
在字符串str
中第一次出现的索引位置,如果未找到则返回 -1。val replacedStr = str.replace("Kotlin", "Java")
:replace
方法将字符串str
中所有的"Kotlin"
替换为"Java"
,并返回替换后的新字符串。
4.5 字符串分割
使用 split
方法可以将字符串按照指定的分隔符分割成多个子字符串,并返回一个列表。
kotlin
val str = "apple,banana,orange"
// 按照逗号分割字符串
val fruits = str.split(",")
for (fruit in fruits) {
println(fruit)
}
val fruits = str.split(",")
:split
方法接受一个分隔符作为参数,这里使用逗号(,
)作为分隔符,将字符串str
分割成多个子字符串,并存储在列表fruits
中。然后使用for
循环遍历列表并打印每个子字符串。
5. 字符串比较
在 Kotlin 中,可以使用 ==
比较两个字符串的内容是否相等,使用 ===
比较两个字符串是否引用同一个对象。
kotlin
val str1 = "Kotlin"
val str2 = "Kotlin"
val str3 = String("Kotlin".toCharArray())
// 比较字符串内容
val isContentEqual1 = str1 == str2
val isContentEqual2 = str1 == str3
println("str1 和 str2 内容是否相等: $isContentEqual1")
println("str1 和 str3 内容是否相等: $isContentEqual2")
// 比较字符串引用
val isReferenceEqual1 = str1 === str2
val isReferenceEqual2 = str1 === str3
println("str1 和 str2 引用是否相等: $isReferenceEqual1")
println("str1 和 str3 引用是否相等: $isReferenceEqual2")
str1 == str2
和str1 == str3
:使用==
比较字符串内容,只要两个字符串的字符序列相同,就返回true
。str1 === str2
和str1 === str3
:使用===
比较字符串引用,只有当两个字符串引用同一个对象时才返回true
。在上述代码中,str1
和str2
可能指向同一个字符串常量对象,而str3
是通过String
构造函数创建的新对象,所以str1 === str3
为false
。
综上所述,Kotlin 中的字符串具有丰富的特性和强大的操作方法,能够满足各种文本处理的需求。通过合理运用这些特性和方法,可以编写出更加高效、简洁的代码。
六、Kotlin 中的选择结构语句
在 Kotlin 中,选择结构语句用于根据不同的条件执行不同的代码块,这在程序中非常重要,可以让程序根据不同的情况做出不同的响应。Kotlin 主要提供了两种选择结构语句:if - else
语句和 when
语句。下面将详细介绍这两种语句。
1. if - else
语句
1.1 基本的 if
语句
基本的 if
语句用于在条件为真时执行特定的代码块。
kotlin
val age = 20
if (age >= 18) {
println("你已经成年了")
}
if
是关键字,用于开始一个条件判断。(age >= 18)
是条件表达式,这里判断变量age
是否大于或等于 18。{}
内的代码是条件为真时要执行的代码块。如果age
确实大于或等于 18,就会执行println("你已经成年了")
这行代码。
1.2 if - else
语句
if - else
语句用于在条件为真时执行一个代码块,条件为假时执行另一个代码块。
kotlin
val age = 15
if (age >= 18) {
println("你已经成年了")
} else {
println("你还未成年")
}
- 如果
age >= 18
条件为真,执行if
代码块中的println("你已经成年了")
。 - 如果条件为假,执行
else
代码块中的println("你还未成年")
。
1.3 嵌套的 if - else
语句
可以在 if
或 else
代码块中嵌套另一个 if - else
语句,以实现更复杂的条件判断。
kotlin
val score = 85
if (score >= 90) {
println("成绩优秀")
} else {
if (score >= 70) {
println("成绩良好")
} else {
if (score >= 60) {
println("成绩及格")
} else {
println("成绩不及格")
}
}
}
- 首先判断
score
是否大于或等于 90,如果是则输出 "成绩优秀"。 - 如果
score
小于 90,进入外层else
代码块,再判断score
是否大于或等于 70,依此类推,根据不同的分数段输出不同的信息。
1.4 if - else if - else
链
为了使嵌套的 if - else
语句更清晰,Kotlin 提供了 if - else if - else
链的形式。
kotlin
val score = 85
if (score >= 90) {
println("成绩优秀")
} else if (score >= 70) {
println("成绩良好")
} else if (score >= 60) {
println("成绩及格")
} else {
println("成绩不及格")
}
- 程序会依次检查每个条件。如果
score >= 90
为真,执行对应的代码块并结束整个if - else if - else
链。 - 如果
score >= 90
为假,继续检查score >= 70
,以此类推,直到找到一个为真的条件或执行else
代码块。
1.5 if
作为表达式
在 Kotlin 中,if
语句可以作为表达式返回一个值,这使得代码更加简洁。
kotlin
val age = 20
val message = if (age >= 18) {
"你已经成年了"
} else {
"你还未成年"
}
println(message)
if
表达式根据age >= 18
的结果返回不同的字符串。- 如果条件为真,返回
"你已经成年了"
;如果条件为假,返回"你还未成年"
。最后将返回的值赋给变量message
并打印。
2. when
语句
2.1 基本的 when
语句
when
语句类似于 Java 中的 switch
语句,但功能更强大,用于根据不同的情况执行不同的代码块。
kotlin
val day = 3
when (day) {
1 -> println("星期一")
2 -> println("星期二")
3 -> println("星期三")
4 -> println("星期四")
5 -> println("星期五")
6, 7 -> println("周末")
else -> println("无效的日期")
}
when
是关键字,后面的(day)
是要进行判断的表达式。1 -> println("星期一")
表示当day
的值为 1 时,执行println("星期一")
代码。6, 7 -> println("周末")
表示当day
的值为 6 或 7 时,执行println("周末")
代码。else
分支用于处理其他未匹配到的情况,类似于switch
语句中的default
分支。
2.2 when
作为表达式
和 if
语句一样,when
语句也可以作为表达式返回一个值。
kotlin
val day = 3
val dayName = when (day) {
1 -> "星期一"
2 -> "星期二"
3 -> "星期三"
4 -> "星期四"
5 -> "星期五"
6, 7 -> "周末"
else -> "无效的日期"
}
println(dayName)
when
表达式根据day
的值返回对应的字符串,最后将返回的值赋给变量dayName
并打印。
2.3 无参数的 when
语句
when
语句可以不指定参数,直接在每个分支中使用布尔表达式进行判断。
kotlin
val score = 85
when {
score >= 90 -> println("成绩优秀")
score >= 70 -> println("成绩良好")
score >= 60 -> println("成绩及格")
else -> println("成绩不及格")
}
- 这种形式的
when
语句会依次检查每个分支的布尔表达式,执行第一个为真的分支代码。如果所有分支都不满足条件,则执行else
分支。
2.4 类型检查和转换
when
语句还可以用于类型检查和转换,结合 is
关键字使用。
kotlin
fun printValue(value: Any) {
when (value) {
is Int -> println("这是一个整数: $value")
is String -> println("这是一个字符串: $value")
is Double -> println("这是一个双精度浮点数: $value")
else -> println("未知类型")
}
}
val num = 10
printValue(num)
is
关键字用于检查value
是否为指定的类型。- 如果
value
是Int
类型,执行对应的代码块并输出相关信息;如果是String
类型或Double
类型,也会执行相应的代码块;如果都不匹配,则执行else
分支。
综上所述,if - else
语句和 when
语句是 Kotlin 中非常重要的选择结构语句,开发者可以根据具体的需求和场景选择合适的语句来实现条件判断和代码分支控制。
七、Kotlin 中的循环结构语句
在 Kotlin 中,循环结构语句用于重复执行特定的代码块,以处理批量数据或执行重复性任务。Kotlin 提供了多种循环结构,包括 for
循环、while
循环和 do - while
循环,下面将详细介绍这些循环结构的用法。
1. for
循环
for
循环主要用于遍历集合或范围,它提供了简洁且灵活的方式来处理一系列元素。
1.1 遍历范围
可以使用 for
循环遍历一个整数范围。
kotlin
// 遍历从 1 到 5 的整数(包含 1 和 5)
for (i in 1..5) {
println(i)
}
for
是关键字,用于开始一个for
循环。i
是循环变量,在每次循环迭代中,i
会依次取范围1..5
中的值。1..5
表示一个从 1 到 5 的闭区间,包含 1 和 5。- 循环体
{ println(i) }
会在每次循环时执行,打印出当前i
的值。
1.2 遍历步长不为 1 的范围
可以使用 step
关键字指定遍历范围的步长。
kotlin
// 从 1 开始,以步长 2 遍历到 10
for (i in 1..10 step 2) {
println(i)
}
step 2
表示每次循环i
的值增加 2,即遍历序列为 1、3、5、7、9。
1.3 反向遍历范围
使用 downTo
关键字可以实现反向遍历范围。
kotlin
// 从 5 反向遍历到 1
for (i in 5 downTo 1) {
println(i)
}
downTo
让循环变量从较大值向较小值递减,这里i
依次取值为 5、4、3、2、1。
1.4 遍历集合
for
循环可以方便地遍历各种集合,如列表、数组等。
kotlin
val numbers = listOf(10, 20, 30)
for (number in numbers) {
println(number)
}
numbers
是一个整数列表,for
循环会依次取出列表中的每个元素,并将其赋值给循环变量number
,然后执行循环体打印该元素。
1.5 遍历集合时获取索引
使用 withIndex()
方法可以在遍历集合时同时获取元素的索引。
kotlin
val fruits = listOf("apple", "banana", "orange")
for ((index, fruit) in fruits.withIndex()) {
println("索引 $index 对应的水果是: $fruit")
}
withIndex()
方法将集合转换为包含索引和元素的序列。(index, fruit)
是解构声明,用于分别获取索引和元素的值,然后在循环体中打印相关信息。
2. while
循环
while
循环在条件为真时重复执行代码块,每次循环开始前都会检查条件是否满足。
kotlin
var count = 0
while (count < 5) {
println(count)
count++
}
var count = 0
:初始化一个计数器变量count
为 0。while (count < 5)
:循环条件,只要count
小于 5,就会执行循环体。- 循环体
{ println(count); count++ }
会打印当前count
的值,并将count
的值加 1。 - 当
count
变为 5 时,条件count < 5
为假,循环结束。
3. do - while
循环
do - while
循环与 while
循环类似,但它会先执行一次循环体,然后再检查条件。这意味着无论条件是否为真,循环体至少会执行一次。
kotlin
var num = 0
do {
println(num)
num++
} while (num < 5)
var num = 0
:初始化变量num
为 0。do
关键字后面的代码块是循环体,会先执行一次,这里打印num
的值并将其加 1。while (num < 5)
:执行完循环体后检查条件,如果num
小于 5,则继续循环;否则,循环结束。
4. 循环控制语句
Kotlin 提供了一些循环控制语句,用于在循环中控制流程,如 break
和 continue
。
4.1 break
语句
break
语句用于立即终止当前所在的循环。
kotlin
for (i in 1..10) {
if (i == 5) {
break
}
println(i)
}
- 当
i
的值等于 5 时,if
条件为真,执行break
语句,循环立即终止,不会再继续执行后续的循环迭代。
4.2 continue
语句
continue
语句用于跳过当前循环迭代的剩余部分,直接进入下一次循环迭代。
kotlin
for (i in 1..10) {
if (i % 2 == 0) {
continue
}
println(i)
}
- 当
i
是偶数时,if
条件为真,执行continue
语句,跳过println(i)
这行代码,直接进入下一次循环迭代,继续处理下一个i
的值。
综上所述,Kotlin 中的循环结构语句提供了丰富的功能和灵活的使用方式,可以满足不同场景下的循环需求。合理运用这些循环结构和控制语句,能够编写出高效、简洁的代码。
八、Kotlin 中的变量类型转换
在 Kotlin 中,变量类型转换分为显式类型转换和安全类型转换,同时还有针对可空类型的特殊转换情况。下面将详细介绍 Kotlin 中各种类型转换的方式和应用场景。
1. 显式类型转换
Kotlin 不支持隐式类型转换,因此在需要进行类型转换时,必须使用显式的转换方法。显式类型转换可以在不同的基本数据类型以及类类型之间进行。
1.1 基本数据类型的显式转换
Kotlin 为基本数据类型提供了一系列的转换方法,例如 toByte()
、toShort()
、toInt()
、toLong()
、toFloat()
、toDouble()
、toChar()
等。
kotlin
fun main() {
// 整数类型之间的转换
val intValue: Int = 10
val byteValue: Byte = intValue.toByte()
val shortValue: Short = intValue.toShort()
val longValue: Long = intValue.toLong()
// 整数转换为浮点数
val floatValue: Float = intValue.toFloat()
val doubleValue: Double = intValue.toDouble()
// 整数转换为字符
val charValue: Char = intValue.toChar()
println("Byte 值: $byteValue")
println("Short 值: $shortValue")
println("Long 值: $longValue")
println("Float 值: $floatValue")
println("Double 值: $doubleValue")
println("Char 值: $charValue")
}
toByte()
:将一个整数转换为Byte
类型。如果原始整数的值超出了Byte
类型的范围(-128 到 127),会发生数据截断。toShort()
:将整数转换为Short
类型,同样可能会有数据截断风险。toLong()
:将整数转换为Long
类型,不会丢失数据,因为Long
类型的取值范围比Int
大。toFloat()
和toDouble()
:将整数转换为浮点数类型,会在转换过程中添加小数部分。toChar()
:将整数转换为对应的 Unicode 字符。
1.2 字符串与基本数据类型的转换
可以将字符串转换为基本数据类型,也可以将基本数据类型转换为字符串。
kotlin
fun main() {
// 字符串转换为整数
val strNumber: String = "20"
val intResult: Int = strNumber.toInt()
// 整数转换为字符串
val num: Int = 30
val strResult: String = num.toString()
println("字符串转换为整数: $intResult")
println("整数转换为字符串: $strResult")
}
toInt()
:将字符串转换为Int
类型。如果字符串不能正确表示一个整数,会抛出NumberFormatException
异常。toString()
:将基本数据类型(如Int
、Float
等)转换为字符串。
2. 安全类型转换
在进行类型转换时,可能会遇到类型不兼容的情况,为了避免抛出 ClassCastException
异常,Kotlin 提供了安全类型转换操作符 as?
。
kotlin
fun main() {
val anyValue: Any = "Hello"
// 安全类型转换为 String
val strResult: String? = anyValue as? String
println("安全转换为 String 结果: $strResult")
// 尝试将 Any 类型转换为 Int
val intResult: Int? = anyValue as? Int
println("安全转换为 Int 结果: $intResult")
}
as?
操作符用于安全地进行类型转换。如果转换成功,返回转换后的类型;如果转换失败,返回null
。- 在上述代码中,
anyValue
实际是一个String
类型,所以anyValue as? String
转换成功,返回该字符串;而anyValue as? Int
转换失败,返回null
。
3. 类型检查与转换结合使用
在进行类型转换之前,通常需要先检查变量的类型,可以使用 is
关键字进行类型检查。
kotlin
fun main() {
val anyValue: Any = 10
if (anyValue is Int) {
// 类型检查通过后,可以安全地进行类型转换
val intValue: Int = anyValue
println("类型检查并转换后的 Int 值: $intValue")
} else {
println("不是 Int 类型")
}
}
is
关键字用于检查变量是否为指定的类型。如果anyValue
是Int
类型,if
条件为真,进入if
代码块。- 在
if
代码块中,由于已经通过类型检查,Kotlin 会自动将anyValue
视为Int
类型,无需显式转换。
4. 可空类型的转换
对于可空类型的变量,在进行类型转换时需要特别注意空值的处理。
kotlin
fun main() {
val nullableStr: String? = "100"
// 可空字符串转换为可空整数
val nullableInt: Int? = nullableStr?.toIntOrNull()
println("可空字符串转换为可空整数: $nullableInt")
val nullValue: String? = null
val nullInt: Int? = nullValue?.toIntOrNull()
println("空字符串转换为可空整数: $nullInt")
}
toIntOrNull()
方法用于将字符串转换为Int
类型,如果字符串不能正确表示一个整数或字符串为null
,则返回null
。- 通过使用安全调用运算符
?.
,可以避免在字符串为null
时调用toIntOrNull()
方法而导致空指针异常。
5. 集合类型的转换
在处理集合时,也可能需要进行类型转换,例如将一个 List<Any>
转换为 List<Int>
。
kotlin
fun main() {
val anyList: List<Any> = listOf(1, 2, 3)
val intList: List<Int> = anyList.filterIsInstance<Int>()
println("集合类型转换结果: $intList")
}
filterIsInstance<Int>()
方法用于过滤集合中的元素,只保留指定类型(这里是Int
类型)的元素,并返回一个新的集合。
综上所述,Kotlin 提供了多种类型转换的方式,开发者可以根据具体的需求和场景选择合适的转换方法,同时要注意处理可能出现的异常和空值情况,以确保代码的健壮性。
九、Kotlin 中的空值处理
在编程中,空值处理是一个非常重要的话题,因为空值往往是导致程序出现空指针异常(NullPointerException)的根源。Kotlin 为了避免空指针异常,在语言层面提供了一系列强大的空值处理机制。以下将详细介绍 Kotlin 中的空值处理方法。
1. 可空类型与非空类型
在 Kotlin 中,类型系统明确区分了可空类型和非空类型。默认情况下,变量声明为非空类型,即不能将 null
赋值给它们;若要允许变量为 null
,则需要使用可空类型,通过在类型后面添加 ?
来表示。
kotlin
// 非空类型的变量,不能赋值为 null
var nonNullableString: String = "Hello"
// 下面这行代码会编译错误,因为 nonNullableString 是非空类型
// nonNullableString = null
// 可空类型的变量,可以赋值为 null
var nullableString: String? = "World"
nullableString = null
var nonNullableString: String = "Hello"
:声明了一个非空的String
类型变量nonNullableString
,它只能存储有效的字符串值,不能为null
。var nullableString: String? = "World"
:声明了一个可空的String
类型变量nullableString
,在声明时可以初始化为有效的字符串,也可以后续将其赋值为null
。
2. 安全调用运算符(?.
)
安全调用运算符 ?.
是 Kotlin 中处理可空类型的一个重要工具,用于在调用可空类型变量的属性或方法时,避免空指针异常。如果变量为 null
,则整个表达式返回 null
,不会执行后续的属性或方法调用。
kotlin
var nullableString: String? = null
// 使用安全调用运算符获取字符串长度
val length1 = nullableString?.length
println("使用安全调用运算符获取长度: $length1")
nullableString = "Hello"
val length2 = nullableString?.length
println("使用安全调用运算符获取长度: $length2")
val length1 = nullableString?.length
:当nullableString
为null
时,nullableString?.length
直接返回null
,不会尝试访问length
属性,从而避免了空指针异常。val length2 = nullableString?.length
:当nullableString
不为null
时,正常调用length
属性获取字符串的长度。
3. Elvis 运算符(?:
)
Elvis 运算符 ?:
用于在可空类型的值为 null
时提供一个默认值。它会先判断左边的可空类型的值是否为 null
,如果为 null
,则返回右边的默认值;如果不为 null
,则返回左边的值。
kotlin
var nullableString: String? = null
// 使用 Elvis 运算符提供默认值
val result = nullableString ?: "默认值"
println("使用 Elvis 运算符的结果: $result")
nullableString = "Kotlin"
val result2 = nullableString ?: "默认值"
println("使用 Elvis 运算符的结果: $result2")
val result = nullableString ?: "默认值"
:由于nullableString
为null
,所以整个表达式返回右边的"默认值"
。val result2 = nullableString ?: "默认值"
:此时nullableString
不为null
,表达式返回nullableString
的值"Kotlin"
。
4. 非空断言运算符(!!
)
非空断言运算符 !!
用于告诉编译器该可空类型的值一定不为 null
。如果实际上该值为 null
,则会抛出空指针异常。因此,使用该运算符时要非常谨慎,确保可空变量确实不为 null
。
kotlin
var nullableString: String? = "Hello"
// 使用非空断言运算符获取字符串长度
val length = nullableString!!.length
println("使用非空断言运算符获取长度: $length")
// 下面这行代码会抛出空指针异常,因为将 nullableString 赋值为 null 后使用了 !! 运算符
// nullableString = null
// val errorLength = nullableString!!.length
val length = nullableString!!.length
:当nullableString
不为null
时,使用!!
运算符可以正常访问其属性或方法。- 如果将
nullableString
赋值为null
后再使用!!
运算符,就会抛出NullPointerException
。
5. let
函数与安全调用结合
let
函数经常与安全调用运算符结合使用,用于在可空变量不为 null
时执行一些操作。
kotlin
var nullableString: String? = "Hello"
nullableString?.let {
// 在 let 函数内部,it 代表非空的 nullableString
println("字符串长度: ${it.length}")
}
nullableString = null
nullableString?.let {
println("字符串长度: ${it.length}")
}
nullableString?.let { ... }
:当nullableString
不为null
时,会执行let
函数内部的代码块,it
代表非空的nullableString
;当nullableString
为null
时,let
函数不会执行。
6. 可空类型集合的处理
在处理可空类型的集合时,可以使用 filterNotNull()
方法过滤掉集合中的 null
值。
kotlin
val nullableList: List<String?> = listOf("Apple", null, "Banana", null, "Cherry")
val nonNullList = nullableList.filterNotNull()
println("过滤掉 null 值后的集合: $nonNullList")
filterNotNull()
方法会遍历集合,将其中的非null
元素提取出来,组成一个新的非空元素集合。
7. 函数参数和返回值的空值处理
在定义函数时,也可以明确指定参数和返回值是否可为空。
kotlin
// 参数为可空类型,返回值为非空类型
fun printAndReturnLength(str: String?): Int {
return str?.length ?: 0
}
val result = printAndReturnLength(null)
println("字符串长度(如果为 null 则返回 0): $result")
fun printAndReturnLength(str: String?): Int
:函数的参数str
为可空的String
类型,返回值为非空的Int
类型。- 在函数内部,使用安全调用运算符和 Elvis 运算符处理
str
可能为null
的情况,确保返回值不为null
。
综上所述,Kotlin 通过可空类型、安全调用运算符、Elvis 运算符等机制,为开发者提供了一套全面且安全的空值处理方案,大大降低了空指针异常的风险,提高了代码的健壮性和可靠性。
十、总结
通过本次课程的学习,我们掌握了 Kotlin 的基本语法格式,了解了变量、运算符、字符串的使用方法,学会了运用选择结构语句和循环结构语句,同时也掌握了变量类型转换和空值处理的技巧。在后续的学习中,可以通过更多的实践来巩固这些知识。
课后提问
如何在Kotlin中声明常量?
Kotlin中的变量类型转换有哪些注意事项?
除了上述提到的,Kotlin还有哪些其他的重要特性?