Kotlin基础语法与类型系统详解
Kotlin基础语法
变量声明
在Kotlin中,变量声明使用 var
关键字用于可变变量,val
关键字用于不可变变量(类似于Java中的 final
变量)。例如:
// 声明一个可变变量
var name: String = "John"
// 声明一个不可变变量
val age: Int = 30
这里,: String
和 : Int
是类型声明。Kotlin 也支持类型推导,所以在很多情况下可以省略类型声明:
var name = "John"
val age = 30
Kotlin编译器会根据初始化值自动推断变量的类型。
数据类型
Kotlin的数据类型分为基本类型和引用类型。基本类型包括数值类型(Byte
、Short
、Int
、Long
、Float
、Double
)、字符类型(Char
)、布尔类型(Boolean
)和字符串类型(String
)。
-
数值类型
Byte
:8位有符号整数,范围是 -128 到 127。Short
:16位有符号整数,范围是 -32768 到 32767。Int
:32位有符号整数,范围是 -2147483648 到 2147483647。Long
:64位有符号整数,范围是 -9223372036854775808 到 9223372036854775807。Float
:32位单精度浮点数。Double
:64位双精度浮点数。
示例:
val byteValue: Byte = 10 val shortValue: Short = 1000 val intValue: Int = 100000 val longValue: Long = 1000000000000000000L val floatValue: Float = 3.14f val doubleValue: Double = 3.141592653589793
注意,
Long
类型的字面值需要在数字后面加上L
,Float
类型的字面值需要在数字后面加上f
。 -
字符类型
Char
类型表示单个字符。字符需要用单引号括起来。例如:
val charValue: Char = 'A'
- 布尔类型
Boolean
类型只有两个值:true
和false
。例如:
val isDone: Boolean = true
- 字符串类型
String
类型用于表示文本。字符串可以用双引号括起来。Kotlin 字符串支持模板表达式,通过${}
语法将变量或表达式嵌入到字符串中。例如:
val name = "John"
val message = "Hello, $name!"
val result = 10 + 20
val expressionMessage = "The result is ${10 + 20}."
运算符
Kotlin 提供了丰富的运算符,包括算术运算符、比较运算符、逻辑运算符、位运算符等。
-
算术运算符
+
:加法-
:减法*
:乘法/
:除法%
:取模
示例:
val a = 10 val b = 3 val sum = a + b val difference = a - b val product = a * b val quotient = a / b val remainder = a % b
-
比较运算符
==
:等于!=
:不等于>
:大于<
:小于>=
:大于等于<=
:小于等于
示例:
val num1 = 10 val num2 = 20 val isEqual = num1 == num2 val isGreater = num1 > num2
-
逻辑运算符
&&
:逻辑与||
:逻辑或!
:逻辑非
示例:
val condition1 = true val condition2 = false val andResult = condition1 && condition2 val orResult = condition1 || condition2 val notResult =!condition1
-
位运算符
and
:按位与or
:按位或xor
:按位异或inv
:按位取反shl
:左移shr
:右移ushr
:无符号右移
示例:
val num = 5 // 二进制表示为 00000101 val andResult = num and 3 // 3 的二进制表示为 00000011,结果为 00000001(即 1)
控制流语句
if - else
语句if - else
语句用于条件判断。在 Kotlin 中,if
表达式是有返回值的,这意味着它可以用作一个值。
val num = 10
val result = if (num > 5) {
"Greater than 5"
} else {
"Less than or equal to 5"
}
when
语句when
语句类似于 Java 中的switch - case
语句,但功能更强大。它可以匹配多种类型,包括对象、范围等。
val day = 3
val dayName = when (day) {
1 -> "Monday"
2 -> "Tuesday"
3 -> "Wednesday"
4 -> "Thursday"
5 -> "Friday"
6 -> "Saturday"
7 -> "Sunday"
else -> "Invalid day"
}
when
也可以用于更复杂的匹配,比如范围匹配:
val num = 15
val result = when (num) {
in 1..10 -> "In the range 1 to 10"
in 11..20 -> "In the range 11 to 20"
else -> "Outside the range"
}
for
循环for
循环用于遍历集合或区间。
// 遍历数组
val numbers = arrayOf(1, 2, 3, 4, 5)
for (number in numbers) {
println(number)
}
// 遍历区间
for (i in 1..5) {
println(i)
}
// 反向遍历区间
for (i in 5 downTo 1) {
println(i)
}
// 遍历区间并指定步长
for (i in 1..5 step 2) {
println(i)
}
while
和do - while
循环while
循环在条件为真时执行循环体。do - while
循环先执行一次循环体,然后再检查条件。
var num = 0
while (num < 5) {
println(num)
num++
}
var num2 = 0
do {
println(num2)
num2++
} while (num2 < 5)
Kotlin类型系统
类型层次结构
Kotlin 的类型层次结构以 Any
为所有非空类型的根类型。Any
类定义了 equals()
、hashCode()
和 toString()
方法。所有类型,包括基本类型的包装类,都继承自 Any
。
Nothing
类型是所有类型的子类型,它表示一个永远不会有值的类型。例如,一个总是抛出异常的函数的返回类型就是 Nothing
。
fun throwException(): Nothing {
throw RuntimeException("This function always throws an exception")
}
Unit
类型只有一个值,即 Unit
。它类似于 Java 中的 void
,用于表示没有有意义返回值的函数。例如:
fun printMessage(): Unit {
println("This is a message")
}
在 Kotlin 中,Unit
类型的返回值可以省略不写,所以上面的函数可以写成:
fun printMessage() {
println("This is a message")
}
可空类型
在 Kotlin 中,类型默认是非空的。如果一个变量可能为 null
,需要在类型后面加上 ?
来表示可空类型。
var name: String? = null
访问可空类型变量的属性或调用其方法时,需要进行空值检查。有几种方式可以做到这一点:
- 使用
if
语句进行显式检查
var name: String? = null
if (name!= null) {
println(name.length)
}
- 安全调用操作符
?.
安全调用操作符允许在对象不为null
时调用其方法或访问其属性,否则返回null
。
var name: String? = null
val length = name?.length
- Elvis 操作符
?:
Elvis 操作符用于在对象为null
时提供一个默认值。
var name: String? = null
val result = name?: "Default name"
- 非空断言操作符
!!
非空断言操作符将可空类型转换为非空类型,如果对象为null
,会抛出NullPointerException
。使用时需谨慎。
var name: String? = null
val length = name!!.length // 如果 name 为 null,这里会抛出 NullPointerException
类型转换
- 自动类型转换
Kotlin 支持数值类型的自动转换。例如,
Byte
类型可以自动转换为Short
、Int
、Long
、Float
和Double
。
val byteValue: Byte = 10
val intValue: Int = byteValue
- 显式类型转换
对于不能自动转换的类型,需要进行显式类型转换。例如,将
Int
转换为Byte
:
val intValue: Int = 100
val byteValue: Byte = intValue.toByte()
Kotlin 为每个数值类型提供了转换方法,如 toByte()
、toShort()
、toInt()
、toLong()
、toFloat()
和 toDouble()
。
泛型
泛型允许在定义类、接口和函数时使用类型参数。例如,定义一个简单的泛型类:
class Box<T>(val value: T) {
fun getValue(): T {
return value
}
}
使用泛型类:
val intBox = Box(10)
val stringBox = Box("Hello")
泛型函数:
fun <T> printValue(value: T) {
println(value)
}
调用泛型函数:
printValue(10)
printValue("Hello")
泛型还支持类型限定,例如:
fun <T : Number> printDoubleValue(value: T) {
println(value.toDouble())
}
这里,类型参数 T
必须是 Number
或其子类型。
类型别名
类型别名允许为现有类型定义一个新的名称。例如:
typealias IntList = List<Int>
val ints: IntList = listOf(1, 2, 3)
类型别名可以使代码更易读,特别是在处理复杂类型时。
密封类
密封类用于表示受限的类继承结构。密封类的所有子类必须在与密封类相同的文件中声明。密封类通常与 when
语句结合使用,以提供更安全和简洁的条件分支。
sealed class Result
class Success(val data: String) : Result()
class Failure(val errorMessage: String) : Result()
fun handleResult(result: Result) {
when (result) {
is Success -> println("Success: ${result.data}")
is Failure -> println("Failure: ${result.errorMessage}")
}
}
在上面的例子中,Result
是密封类,Success
和 Failure
是它的子类。when
语句在处理 Result
类型时,编译器可以确保所有可能的子类型都被处理。
枚举类
枚举类用于定义一组命名的常量。例如:
enum class Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
枚举类可以有属性和方法。例如:
enum class Day(val index: Int) {
MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7)
}
可以通过 Day.MONDAY.index
访问枚举常量的属性。
数组
Kotlin 中的数组由 Array
类表示。可以通过 arrayOf()
函数创建数组:
val numbers = arrayOf(1, 2, 3, 4, 5)
也可以创建特定类型的数组,例如 IntArray
:
val intArray = intArrayOf(1, 2, 3, 4, 5)
数组元素可以通过索引访问:
val firstNumber = numbers[0]
集合
Kotlin 提供了丰富的集合类型,包括列表(List
)、集合(Set
)和映射(Map
)。
-
列表
- 不可变列表:
List
接口表示不可变列表,通过listOf()
函数创建。
val numbers = listOf(1, 2, 3, 4, 5)
- 可变列表:
MutableList
接口表示可变列表,通过mutableListOf()
函数创建。
val mutableNumbers = mutableListOf(1, 2, 3, 4, 5) mutableNumbers.add(6)
- 不可变列表:
-
集合
- 不可变集合:
Set
接口表示不可变集合,通过setOf()
函数创建。
val uniqueNumbers = setOf(1, 2, 3, 3, 4, 5) // 集合会自动去除重复元素
- 可变集合:
MutableSet
接口表示可变集合,通过mutableSetOf()
函数创建。
val mutableUniqueNumbers = mutableSetOf(1, 2, 3) mutableUniqueNumbers.add(4)
- 不可变集合:
-
映射
- 不可变映射:
Map
接口表示不可变映射,通过mapOf()
函数创建。
val nameAgeMap = mapOf("John" to 30, "Jane" to 25)
- 可变映射:
MutableMap
接口表示可变映射,通过mutableMapOf()
函数创建。
val mutableNameAgeMap = mutableMapOf("John" to 30) mutableNameAgeMap.put("Jane", 25)
- 不可变映射:
Kotlin 的集合框架提供了丰富的操作函数,如过滤、映射、折叠等,使得对集合的操作更加方便和高效。例如:
val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }
val squaredNumbers = numbers.map { it * it }
通过深入了解 Kotlin 的基础语法和类型系统,开发者可以更加高效地编写 Kotlin 代码,充分发挥 Kotlin 在现代软件开发中的优势。无论是开发 Android 应用,还是服务器端应用,Kotlin 的简洁语法和强大的类型系统都能提供良好的编程体验。