跳到主要内容

Kotlin 基础语法

本章介绍 Kotlin 的基础语法,包括变量定义、数据类型、运算符等内容。掌握这些基础知识是编写 Kotlin 程序的前提。

变量定义

Kotlin 使用 valvar 关键字来定义变量:

  • val:定义只读变量(相当于 Java 的 final),赋值后不可修改
  • var:定义可变变量,可以多次赋值
// val - 不可变变量(推荐优先使用)
val name = "Kotlin"
val version = 1.9
// name = "Java" // 编译错误:val 不能重新赋值

// var - 可变变量
var count = 0
count = 10 // 可以重新赋值
count += 5 // count 现在是 15

显式指定类型

Kotlin 支持类型推断,但也可以显式指定类型:

// 类型推断
val message = "Hello" // 编译器推断为 String
val number = 42 // 编译器推断为 Int

// 显式指定类型
val greeting: String = "Hello World"
val age: Int = 25
val price: Double = 19.99
val isActive: Boolean = true

延迟初始化

// lateinit - 用于 var,延迟初始化
lateinit var networkManager: NetworkManager

fun init() {
networkManager = NetworkManager()
}

// lazy - 用于 val,首次访问时初始化
val database: Database by lazy {
println("Initializing database...")
Database.connect()
}

基本数据类型

Kotlin 的基本数据类型与 Java 类似,但都是对象类型:

数字类型

// 整数类型
val byte: Byte = 127 // 8位,-128 到 127
val short: Short = 32767 // 16位,-32768 到 32767
val int: Int = 2147483647 // 32位,约 -21亿 到 21亿
val long: Long = 9223372036854775807L // 64位,需要加 L 后缀

// 浮点类型
val float: Float = 3.14F // 32位,需要加 F 后缀
val double: Double = 3.1415926535 // 64位,默认浮点类型

// 数字字面量
val oneMillion = 1_000_000 // 使用下划线增加可读性
val creditCardNumber = 1234_5678_9012_3456L

字符和字符串

// 字符
val char: Char = 'A'
val digit: Char = '9'
val unicode: Char = '\u0041' // 'A'

// 字符串
val str: String = "Hello Kotlin"

// 多行字符串
val multiline = """
这是多行字符串
可以包含"引号"和特殊字符
不需要转义
""".trimIndent()

// 字符串模板
val name = "Kotlin"
val version = 1.9
val info = "Language: $name, Version: $version"

// 表达式模板
val a = 10
val b = 20
val result = "$a + $b = ${a + b}" // "10 + 20 = 30"

多美元字符串插值(Kotlin 2.1 预览)

实验性特性

多美元字符串插值是 Kotlin 2.1 的预览特性,需要启用编译选项:

// build.gradle.kts
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xmulti-dollar-interpolation")
}
}

当字符串中需要包含大量美元符号时(如 JSON Schema、模板引擎),可以使用多美元前缀来避免频繁转义:

// 传统方式:需要转义
val jsonSchema = """
{
"${'$'}schema": "https://json-schema.org/draft/2020-12/schema",
"${'$'}id": "https://example.com/schema.json"
}
"""

// 多美元插值:$$ 表示需要两个美元符号才能触发插值
val schema = $$"""
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schema.json",
"title": "$${name}" // 这里会触发插值
}
"""

// 三美元前缀:需要 $$$ 才触发插义
val template = $$$"""
Price: $$amount // 两个美元符号,不触发插值
Total: $$$${calculateTotal()} // 三个美元符号,触发插值
"""

布尔类型

val isTrue: Boolean = true
val isFalse: Boolean = false

// 布尔运算
val andResult = isTrue && isFalse // false(与)
val orResult = isTrue || isFalse // true(或)
val notResult = !isTrue // false(非)

数组

// 创建数组
val numbers = arrayOf(1, 2, 3, 4, 5)
val strings = arrayOf("Kotlin", "Java", "Python")

// 创建特定类型数组
val intArray = intArrayOf(1, 2, 3)
val doubleArray = doubleArrayOf(1.1, 2.2, 3.3)

// 创建指定大小的数组
val sizedArray = Array(5) { i -> i * 2 } // [0, 2, 4, 6, 8]

// 数组操作
val first = numbers[0] // 访问元素
numbers[0] = 10 // 修改元素
val length = numbers.size // 数组长度
val contains = 3 in numbers // 是否包含

类型转换

Kotlin 不支持隐式类型转换,需要显式转换:

val intValue: Int = 100

// 显式转换
val longValue: Long = intValue.toLong()
val doubleValue: Double = intValue.toDouble()
val stringValue: String = intValue.toString()

// 字符串转数字
val strNumber = "123"
val number = strNumber.toInt()
val safeNumber = strNumber.toIntOrNull() // 转换失败返回 null

// 安全转换
val invalidNumber = "abc"
val result = invalidNumber.toIntOrNull() ?: 0 // 转换失败使用默认值

运算符

算术运算符

val a = 10
val b = 3

val sum = a + b // 13(加法)
val difference = a - b // 7(减法)
val product = a * b // 30(乘法)
val quotient = a / b // 3(整数除法)
val remainder = a % b // 1(取余)

// 浮点除法
val floatDiv = a.toDouble() / b // 3.333...

赋值运算符

var x = 10

x += 5 // x = x + 5,结果是 15
x -= 3 // x = x - 3,结果是 12
x *= 2 // x = x * 2,结果是 24
x /= 4 // x = x / 4,结果是 6
x %= 4 // x = x % 4,结果是 2

比较运算符

val a = 10
val b = 20

val isEqual = a == b // false(等于)
val isNotEqual = a != b // true(不等于)
val isGreater = a > b // false(大于)
val isLess = a < b // true(小于)
val isGreaterOrEqual = a >= b // false(大于等于)
val isLessOrEqual = a <= b // true(小于等于)

逻辑运算符

val condition1 = true
val condition2 = false

val andResult = condition1 && condition2 // false(与)
val orResult = condition1 || condition2 // true(或)
val notResult = !condition1 // false(非)

// 短路特性
val result = condition1 && someFunction() // condition1 为 false 时不会调用 someFunction()

位运算符

val a = 0b1100  // 12
val b = 0b1010 // 10

val and = a and b // 0b1000 = 8(按位与)
val or = a or b // 0b1110 = 14(按位或)
val xor = a xor b // 0b0110 = 6(按位异或)
val inv = a.inv() // 按位取反
val leftShift = a shl 2 // 左移 2 位
val rightShift = a shr 2 // 右移 2 位

范围运算符

// 闭区间(包含起始和结束)
val range = 1..10 // 1, 2, 3, ..., 10

// 半开区间(包含起始,不包含结束)
val halfOpen = 1 until 10 // 1, 2, 3, ..., 9

// 降序范围
val descending = 10 downTo 1

// 带步长
val withStep = 1..10 step 2 // 1, 3, 5, 7, 9

// 范围检查
val x = 5
val inRange = x in 1..10 // true
val notInRange = x !in 1..4 // true

字符串操作

val str = "Hello Kotlin"

// 字符串长度
val length = str.length // 12

// 获取字符
val firstChar = str[0] // 'H'
val lastChar = str[str.length - 1] // 'n'

// 子字符串
val substring = str.substring(0, 5) // "Hello"
val substring2 = str.substring(6) // "Kotlin"

// 字符串比较
val str1 = "Kotlin"
val str2 = "kotlin"
val isSame = str1 == str2 // false(区分大小写)
val isSameIgnoreCase = str1.equals(str2, ignoreCase = true) // true

// 字符串查找
val contains = str.contains("Kotlin") // true
val startsWith = str.startsWith("Hello") // true
val endsWith = str.endsWith("!") // false
val index = str.indexOf("Kotlin") // 6

// 字符串替换
val replaced = str.replace("Kotlin", "World") // "Hello World"

// 字符串分割
val split = "a,b,c".split(",") // ["a", "b", "c"]

// 字符串修剪
val trimmed = " hello ".trim() // "hello"

// 判空
val empty = ""
val isEmpty = empty.isEmpty() // true(长度为0)
val isBlank = " ".isBlank() // true(空或仅空白字符)
val isNotEmpty = str.isNotEmpty() // true

空安全

Kotlin 的类型系统区分可空类型和不可空类型:

// 不可空类型(默认)
var nonNull: String = "Hello"
// nonNull = null // 编译错误

// 可空类型(类型后加 ?)
var nullable: String? = "Hello"
nullable = null // 可以赋值为 null

// 安全调用操作符 ?.
val length = nullable?.length // 如果 nullable 为 null,返回 null

// Elvis 操作符 ?:(提供默认值)
val len = nullable?.length ?: 0 // 如果为 null,使用 0

// 非空断言操作符 !!(慎用)
val forceLength = nullable!!.length // 如果为 null,抛出 NullPointerException

// 安全类型转换
val obj: Any = "Hello"
val str: String? = obj as? String // 如果转换失败,返回 null

注释

// 单行注释

/*
* 多行注释
* 可以跨越多行
*/

/**
* KDoc 文档注释
* 用于生成 API 文档
* @param name 参数说明
* @return 返回值说明
*/
fun greet(name: String): String {
return "Hello, $name"
}

最佳实践

1. 优先使用 val

// 推荐
val name = "Kotlin"
val items = listOf("a", "b", "c")

// 避免(除非确实需要修改)
var name = "Kotlin"

2. 使用类型推断

// 推荐
val message = "Hello"
val count = 42

// 避免(除非需要明确类型)
val message: String = "Hello"
val count: Int = 42

3. 使用字符串模板

// 推荐
val name = "Kotlin"
val message = "Hello, $name!"

// 避免
val message = "Hello, " + name + "!"

4. 安全处理可空类型

// 推荐
val length = nullable?.length ?: 0

// 避免(可能抛出异常)
val length = nullable!!.length

小结

  1. 变量:使用 val(不可变)和 var(可变)定义变量
  2. 数据类型:数字、字符、字符串、布尔、数组
  3. 类型转换:需要显式转换,使用 toXxx() 方法
  4. 运算符:算术、赋值、比较、逻辑、位运算、范围
  5. 字符串:支持模板、丰富的操作方法
  6. 空安全:类型系统区分可空和不可空类型

练习

  1. 定义不同类型的变量并打印它们的值
  2. 编写程序计算圆的面积和周长
  3. 使用字符串模板格式化输出个人信息
  4. 实现一个安全的类型转换函数
  5. 使用范围运算符遍历数字并打印