Kotlin 基础语法教程:快速入门篇 – wiki基地


Kotlin 基础语法教程:快速入门篇

Kotlin 是一种现代化的、静态类型的编程语言,由 JetBrains 公司开发,并于 2017 年被 Google 宣布为 Android 官方开发语言。它以其简洁、安全、与 Java 的高度互操作性以及对多平台开发的支持而迅速流行起来。本教程旨在为初学者提供一个 Kotlin 基础语法的快速入门指南,帮助你快速掌握这门强大语言的核心概念。

1. 为什么选择 Kotlin?

在深入语法之前,让我们简要了解一下 Kotlin 的主要优势:

  • 简洁性 (Conciseness): Kotlin 能用更少的代码表达相同的逻辑,减少样板代码,提高开发效率和代码可读性。
  • 安全性 (Safety): Kotlin 的类型系统旨在从根源上消除空指针异常(NullPointerException, NPE)的风险,这是 Java 中最常见的运行时错误之一。
  • 互操作性 (Interoperability): Kotlin 与 Java 100% 兼容。你可以在 Kotlin 项目中无缝调用 Java 代码,反之亦然。这使得在现有 Java 项目中逐步引入 Kotlin 成为可能。
  • 多平台 (Multiplatform): Kotlin 不仅仅局限于 JVM(服务器端、Android)。通过 Kotlin Multiplatform Mobile (KMM) 和 Kotlin/JS、Kotlin/Native,你可以使用 Kotlin 编写 iOS、Web 前端、后端、桌面应用甚至嵌入式系统的代码,实现代码共享。
  • 强大的工具支持: 作为由顶级 IDE 开发者 JetBrains 创建的语言,Kotlin 拥有极其出色的工具支持,尤其是在 IntelliJ IDEA 和 Android Studio 中。

2. 环境搭建

开始学习 Kotlin 最简单的方式是:

  • 在线 Playground: 访问 Kotlin Playground,无需任何安装即可在线编写和运行 Kotlin 代码。
  • 本地 IDE:
    • IntelliJ IDEA: JetBrains 官方 IDE,对 Kotlin 提供最佳支持。社区版 (Community Edition) 是免费的。下载并安装 IntelliJ IDEA,创建新项目时选择 Kotlin 即可。
    • Android Studio: 如果你打算进行 Android 开发,Android Studio(基于 IntelliJ IDEA)是首选,它内置了对 Kotlin 的全面支持。
    • 其他编辑器: VS Code 等编辑器也可以通过安装 Kotlin 插件来支持 Kotlin 开发,但对于初学者,推荐使用 IntelliJ IDEA 或 Android Studio。

本教程的代码示例假定你已具备运行 Kotlin 代码的环境。

3. 第一个 Kotlin 程序:”Hello, World!”

按照传统,我们从 “Hello, World!” 开始。创建一个名为 HelloWorld.kt 的文件(Kotlin 文件通常以 .kt 结尾),并输入以下代码:

“`kotlin
// 包声明 (可选,但推荐)
package com.example.basics

// 主函数 – 程序的入口点
fun main() {
// 使用 println 输出一行文本到控制台
println(“Hello, Kotlin World!”)
}
“`

  • package com.example.basics: 定义了文件所属的包。包用于组织代码,避免命名冲突。这是一个良好的实践,尽管对于非常小的程序是可选的。
  • fun main() { ... }: 这是程序的入口点函数。当你运行 Kotlin 程序时,JVM 会寻找并执行这个 main 函数。fun 是 Kotlin 中定义函数的关键字。
  • println("Hello, Kotlin World!"): 调用标准库函数 println,它会将括号内的字符串输出到标准输出(通常是控制台),并在末尾添加一个换行符。
  • //: 单行注释。Kotlin 也支持多行注释 /* ... */

在 IntelliJ IDEA 或 Android Studio 中,你可以直接点击 main 函数旁边的绿色运行按钮来执行这段代码。

4. 变量声明:valvar

Kotlin 使用两个关键字来声明变量:

  • val (Value): 用于声明只读(不可变)变量。一旦 val 变量被赋值,就不能再重新赋值。这类似于 Java 中的 final 变量。推荐优先使用 val,以增强代码的不可变性和可预测性。
  • var (Variable): 用于声明可变变量。var 变量的值可以在声明后被修改。

“`kotlin
fun main() {
// 声明一个只读变量 message,类型由编译器推断为 String
val message = “Welcome to Kotlin!”
// message = “Another message” // 编译错误!val 不能被重新赋值

// 声明一个可变变量 counter,类型被推断为 Int
var counter = 0
println("Initial counter: $counter") // 输出: Initial counter: 0

counter = counter + 1 // 可以修改 var 变量的值
// 或者更简洁地: counter++
println("Updated counter: $counter") // 输出: Updated counter: 1

// 显式声明类型
val pi: Double = 3.14159
var name: String = "Alice"

println("Pi value: $pi")
println("User name: $name")

}
“`

  • 类型推断 (Type Inference): Kotlin 编译器通常能根据赋给变量的初始值自动推断出变量的类型。如 val message = "...",编译器知道 messageString 类型。
  • 显式类型声明: 你也可以在变量名后加上冒号 (:) 和类型来显式声明变量类型,如 val pi: Double = 3.14159。当编译器无法推断或你希望代码更清晰时,可以使用显式声明。
  • 字符串模板 (String Templates): 注意 println 中的 $counter$pi。这是 Kotlin 的字符串模板功能,允许你直接在字符串字面量中嵌入变量或表达式。使用 $ 符号引用简单变量,使用 ${...} 引用更复杂的表达式,例如 ${counter + 1}

5. 基本数据类型

Kotlin 提供了一套丰富的基本数据类型,与 Java 类似但有一些关键区别(例如,Kotlin 中的所有东西都是对象,包括基本类型):

  • 数字类型:
    • Int: 32位整数 (常用)
    • Long: 64位整数 (用于需要更大范围的整数,数值后加 L,如 123L)
    • Short: 16位整数
    • Byte: 8位整数
    • Double: 64位浮点数 (常用,默认浮点类型)
    • Float: 32位浮点数 (数值后加 fF,如 3.14f)
  • 布尔类型:
    • Boolean: 值为 truefalse
  • 字符类型:
    • Char: 表示单个字符,用单引号括起来,如 'A', '\n' (换行符)
  • 字符串类型:
    • String: 表示文本序列,用双引号括起来,如 "Hello"。字符串是不可变的。

“`kotlin
fun main() {
val myInt: Int = 100
val myLong: Long = 9876543210L
val myDouble: Double = 123.45
val myFloat: Float = 67.89f
val myBoolean: Boolean = true
val myChar: Char = ‘K’
val myString: String = “Kotlin is fun!”

println("Int: $myInt")
println("Long: $myLong")
println("Double: $myDouble")
println("Float: $myFloat")
println("Boolean: $myBoolean")
println("Char: $myChar")
println("String: $myString")

// 类型转换需要显式调用转换函数
val anInt: Int = 10
// val aLong: Long = anInt // 编译错误!不能隐式转换
val aLong: Long = anInt.toLong() // 正确,显式转换
println("Converted Long: $aLong")

val doubleValue: Double = 3.7
val intValue: Int = doubleValue.toInt() // 截断小数部分
println("Double to Int: $intValue") // 输出: Double to Int: 3

}
“`

注意: Kotlin 不支持数字类型之间的隐式转换(如 int 自动转 long)。必须使用明确的转换函数(如 toInt(), toDouble(), toLong() 等)来进行转换。

6. 空安全 (Null Safety) – Kotlin 的核心特性

Kotlin 的类型系统旨在消除 NullPointerException。默认情况下,Kotlin 中的类型是非空 (non-nullable) 的,意味着它们不能持有 null 值。

“`kotlin
fun main() {
var nonNullableString: String = “Hello”
// nonNullableString = null // 编译错误!String 类型不能持有 null

// 如果需要允许变量持有 null,必须在类型声明后加上问号 (?)
var nullableString: String? = "Kotlin"
println("Nullable string initially: $nullableString") // 输出: Nullable string initially: Kotlin

nullableString = null // 这是允许的,因为类型是 String?
println("Nullable string after setting to null: $nullableString") // 输出: Nullable string after setting to null: null

// 如何安全地使用可空类型?

// 1. 安全调用操作符 (?.)
// 如果 nullableString 非 null,则调用 length 属性;否则,整个表达式结果为 null。
val length: Int? = nullableString?.length
println("Length using safe call: $length") // 输出: Length using safe call: null (因为 nullableString 是 null)

// 2. Elvis 操作符 (?:) - 提供默认值
// 如果 nullableString?.length 的结果是 null,则使用 ?: 右侧的值 (0)。
val lenOrDefault: Int = nullableString?.length ?: 0
println("Length or default value: $lenOrDefault") // 输出: Length or default value: 0

// 3. 安全调用与 let 函数 (?.) + let { ... }
// 只有当 nullableString 非 null 时,let 块内的代码才会执行。
// 在 let 块内,`it` 引用非空的值。
nullableString = "Not Null Anymore"
nullableString?.let {
    println("Inside let block: String is '$it' and its length is ${it.length}")
    // 输出: Inside let block: String is 'Not Null Anymore' and its length is 18
}

// 4. 非空断言操作符 (!!) - 谨慎使用!
// 强制告诉编译器,你确定这个可空变量此时此刻不是 null。
// 如果实际上它是 null,程序将抛出 NullPointerException!
// 通常应避免使用,除非你 100% 确定。
// val mustBeNonNull: String = nullableString!! // 如果 nullableString 此时是 null,会崩溃!
// println(mustBeNonNull.length)

// 正确的检查方式 (智能转换 Smart Casts)
val anotherNullable: String? = "Maybe Null"
if (anotherNullable != null) {
    // 在这个 if 块内部,编译器知道 anotherNullable 不是 null,
    // 所以你可以像非空类型一样直接使用它,无需 ?.
    println("Length inside null check: ${anotherNullable.length}") // 输出: Length inside null check: 10
} else {
    println("The string was null.")
}

}
“`

掌握 Kotlin 的空安全机制是编写健壮 Kotlin 代码的关键。优先使用 ?.?:,以及 if 检查,尽量避免使用 !!

7. 控制流语句

7.1 if / else 表达式

在 Kotlin 中,if 是一个表达式,意味着它可以返回值。

“`kotlin
fun main() {
val a = 10
val b = 20

// 传统用法
var maxVal: Int
if (a > b) {
    maxVal = a
} else {
    maxVal = b
}
println("Max value (traditional): $maxVal") // 输出: Max value (traditional): 20

// 作为表达式使用
val maxResult = if (a > b) {
    println("Choosing a")
    a // if 块的最后一个表达式是返回值
} else {
    println("Choosing b")
    b // else 块的最后一个表达式是返回值
}
println("Max value (expression): $maxResult") // 输出: Choosing b  Max value (expression): 20

// 更简洁的单行表达式
val minResult = if (a < b) a else b
println("Min value (expression): $minResult") // 输出: Min value (expression): 10

// if/else if/else 链
val score = 75
val grade = if (score >= 90) {
    "A"
} else if (score >= 80) {
    "B"
} else if (score >= 70) {
    "C"
} else if (score >= 60) {
    "D"
} else {
    "F"
}
println("Grade: $grade") // 输出: Grade: C

}
“`

7.2 when 表达式

when 是 Kotlin 中对 Java switch 语句的强大替代品。它同样可以作为表达式返回值。

“`kotlin
fun main() {
val day = 3

// 基本用法,类似 switch
val dayName = when (day) {
    1 -> "Monday"
    2 -> "Tuesday"
    3 -> "Wednesday"
    4 -> "Thursday"
    5 -> "Friday"
    6 -> "Saturday"
    7 -> "Sunday"
    else -> "Invalid day" // 必须有 else 分支,除非所有可能情况都已覆盖
}
println("Day $day is $dayName") // 输出: Day 3 is Wednesday

// 合并多个分支
val typeOfDay = when (day) {
    1, 2, 3, 4, 5 -> "Weekday"
    6, 7 -> "Weekend"
    else -> "Invalid day"
}
println("Day $day is a $typeOfDay") // 输出: Day 3 is a Weekday

// 使用 `in` 检查范围或集合
val num = 15
val numDescription = when (num) {
    in 1..10 -> "Small number"
    in 11..100 -> "Medium number"
    !in 1..100 -> "Out of range (1-100)" // 使用 !in
    else -> "Exactly 100?" // 其实这里逻辑有点问题,应该先判断11-100
}
println("$num is a $numDescription") // 输出: 15 is a Medium number

// 使用 `is` 检查类型 (配合智能转换)
val x: Any = "Hello" // Any 是 Kotlin 中所有类的超类
when (x) {
    is String -> println("It's a String with length ${x.length}") // 智能转换为 String
    is Int -> println("It's an Int with value $x")
    is Boolean -> println("It's a Boolean: $x")
    else -> println("Unknown type")
} // 输出: It's a String with length 5

// 不带参数的 when,相当于 if-else if 链
val number = -5
val sign = when {
    number > 0 -> "positive"
    number < 0 -> "negative"
    else -> "zero"
}
println("Number $number is $sign") // 输出: Number -5 is negative

}
“`

when 非常灵活和强大,是 Kotlin 中常用的控制流结构。

7.3 for 循环

Kotlin 的 for 循环主要用于迭代任何提供迭代器(iterator)的对象,最常见的是范围(ranges)和集合(collections)。

“`kotlin
fun main() {
// 1. 迭代范围 (Ranges)
println(“Counting from 1 to 5:”)
for (i in 1..5) { // 包含 5 (闭区间)
print(“$i “)
}
println() // 输出: 1 2 3 4 5

println("Counting from 1 until 5:")
for (i in 1 until 5) { // 不包含 5 (半开区间)
    print("$i ")
}
println() // 输出: 1 2 3 4

println("Counting down from 5 to 1:")
for (i in 5 downTo 1) {
    print("$i ")
}
println() // 输出: 5 4 3 2 1

println("Counting from 1 to 10 with step 2:")
for (i in 1..10 step 2) {
    print("$i ")
}
println() // 输出: 1 3 5 7 9

// 2. 迭代集合 (Collections)
val fruits = listOf("Apple", "Banana", "Cherry")
println("Fruits:")
for (fruit in fruits) {
    println("- $fruit")
}
/* 输出:
- Apple
- Banana
- Cherry
*/

// 迭代集合并获取索引
println("Fruits with index:")
for ((index, fruit) in fruits.withIndex()) {
    println("  Index $index: $fruit")
}
/* 输出:
  Index 0: Apple
  Index 1: Banana
  Index 2: Cherry
*/

// 3. 迭代 Map
val userAges = mapOf("Alice" to 30, "Bob" to 25, "Charlie" to 35)
println("User ages:")
for ((name, age) in userAges) { // 解构声明 (Destructuring Declaration)
    println("- $name is $age years old")
}
/* 输出:
- Alice is 30 years old
- Bob is 25 years old
- Charlie is 35 years old
*/

}
“`

7.4 whiledo-while 循环

这两个循环与 Java 或 C++ 中的工作方式类似。

“`kotlin
fun main() {
// while 循环:先判断条件,再执行循环体
var i = 0
println(“While loop:”)
while (i < 5) {
print(“$i “)
i++
}
println() // 输出: 0 1 2 3 4

// do-while 循环:先执行一次循环体,再判断条件
var j = 5
println("Do-while loop:")
do {
    print("$j ")
    j--
} while (j > 0)
println() // 输出: 5 4 3 2 1

}
“`

8. 函数 (Functions)

函数是组织代码的基本单元。

“`kotlin
// 1. 基本函数定义
// fun关键字 函数名(参数名: 参数类型, …): 返回类型 { 函数体 }
fun greet(name: String): String {
return “Hello, $name!”
}

// 2. 返回 Unit 的函数 (相当于 Java 的 void)
// 如果函数不返回任何有意义的值,返回类型是 Unit,可以省略
fun printMessage(message: String) { // 等同于 fun printMessage(message: String): Unit {
println(message)
}

// 3. 单表达式函数 (简洁语法)
// 如果函数体只有一个表达式,可以用 = 直接指定,返回类型可推断
fun add(a: Int, b: Int) = a + b // 返回类型被推断为 Int

fun multiply(a: Double, b: Double): Double = a * b // 显式声明返回类型

// 4. 默认参数 (Default Arguments)
fun sendMessage(message: String, sender: String = “System”) {
println(“From $sender: $message”)
}

// 5. 命名参数 (Named Arguments)
// 调用函数时,可以指定参数名,这样可以不按顺序传递参数,提高可读性
fun displayInfo(name: String, age: Int, city: String) {
println(“Name: $name, Age: $age, City: $city”)
}

fun main() {
// 调用函数
val greeting = greet(“Kotlin User”)
println(greeting) // 输出: Hello, Kotlin User!

printMessage("This is a message.") // 输出: This is a message.

val sum = add(5, 3)
println("Sum: $sum") // 输出: Sum: 8

val product = multiply(2.5, 4.0)
println("Product: $product") // 输出: Product: 10.0

// 使用默认参数
sendMessage("System update required.") // sender 使用默认值 "System"
sendMessage("Meeting cancelled.", "Alice") // 指定 sender

// 使用命名参数
displayInfo("Bob", 28, "New York") // 按顺序
displayInfo(city = "London", name = "Charlie", age = 35) // 使用命名参数,顺序任意
displayInfo(name = "David", city = "Paris", age = 40) // 混合使用也可以,但命名参数需在最后

}
“`

默认参数和命名参数极大地提高了函数调用的灵活性和可读性。

9. 基础集合 (Collections)

Kotlin 标准库提供了丰富的集合类型,主要分为只读 (read-only)可变 (mutable) 两类。

  • List: 有序集合,允许重复元素。
    • listOf(): 创建只读 List。
    • mutableListOf(): 创建可变 MutableList。
  • Set: 无序集合,不允许重复元素。
    • setOf(): 创建只读 Set。
    • mutableSetOf(): 创建可变 MutableSet。
  • Map: 键值对集合,键是唯一的。
    • mapOf(): 创建只读 Map。
    • mutableMapOf(): 创建可变 MutableMap。

“`kotlin
fun main() {
// List
val readOnlyList: List = listOf(“a”, “b”, “c”, “a”) // 只读,允许重复
println(“Read-only List: $readOnlyList”) // 输出: [a, b, c, a]
println(“First element: ${readOnlyList[0]}”) // 通过索引访问
println(“List size: ${readOnlyList.size}”)

val mutableList: MutableList<Int> = mutableListOf(1, 2, 3)
println("Mutable List (before): $mutableList") // 输出: [1, 2, 3]
mutableList.add(4) // 添加元素
mutableList.removeAt(0) // 按索引移除
mutableList[0] = 10 // 修改元素
println("Mutable List (after): $mutableList") // 输出: [10, 3, 4]

// Set
val readOnlySet: Set<Char> = setOf('x', 'y', 'z', 'x') // 只读,自动去重
println("Read-only Set: $readOnlySet") // 输出: [x, y, z] (顺序可能不同)
println("Set contains 'y': ${readOnlySet.contains('y')}") // 检查元素是否存在

val mutableSet: MutableSet<Double> = mutableSetOf(1.1, 2.2)
mutableSet.add(3.3)
mutableSet.add(1.1) // 添加重复元素无效
println("Mutable Set: $mutableSet") // 输出: [1.1, 2.2, 3.3] (顺序可能不同)

// Map
val readOnlyMap: Map<String, Int> = mapOf("one" to 1, "two" to 2, "three" to 3)
println("Read-only Map: $readOnlyMap") // 输出: {one=1, two=2, three=3}
println("Value for key 'two': ${readOnlyMap["two"]}") // 通过键访问值
println("Map keys: ${readOnlyMap.keys}")
println("Map values: ${readOnlyMap.values}")

val mutableMap: MutableMap<String, String> = mutableMapOf("lang" to "Kotlin", "ide" to "IntelliJ")
mutableMap["platform"] = "JVM" // 添加或更新键值对
mutableMap["ide"] = "IntelliJ IDEA" // 更新值
println("Mutable Map: $mutableMap") // 输出: {lang=Kotlin, ide=IntelliJ IDEA, platform=JVM}

}
“`

优先使用只读集合,只有在确实需要修改集合时才使用可变集合,这有助于编写更安全、更易于推理的代码。

10. 类与对象 (基础)

Kotlin 是一门面向对象的语言(也支持函数式编程范式)。定义类非常简单。

“`kotlin
// 定义一个简单的 Person 类
// 主构造函数 (Primary Constructor) 直接在类名后声明
// val/var 关键字使构造函数参数成为类的属性
class Person(val name: String, var age: Int) {
// 可以添加方法 (成员函数)
fun greet() {
println(“Hello, my name is $name and I am $age years old.”)
}

// 也可以添加其他属性
var city: String? = null // 可空属性,需要初始化或设为 null

}

fun main() {
// 创建类的实例 (对象),注意 Kotlin 没有 new 关键字
val person1 = Person(“Alice”, 30)
val person2 = Person(“Bob”, 25)

// 访问属性
println("${person1.name}'s age: ${person1.age}") // 输出: Alice's age: 30

// 修改可变属性
person2.age = 26
println("${person2.name}'s new age: ${person2.age}") // 输出: Bob's new age: 26

// 调用方法
person1.greet() // 输出: Hello, my name is Alice and I am 30 years old.
person2.greet() // 输出: Hello, my name is Bob and I am 26 years old.

// 设置可选属性
person1.city = "New York"
println("${person1.name} lives in ${person1.city ?: "an unknown city"}") // 使用 Elvis 操作符处理 null

}
“`

这只是类和对象的基础。Kotlin 的面向对象特性还包括继承、接口、数据类 (data class)、枚举类 (enum class)、密封类 (sealed class) 等,这些是更进阶的主题。

11. 总结与后续学习

恭喜你!你已经学习了 Kotlin 的基础语法,包括:

  • 变量声明 (val, var) 与基本类型
  • 至关重要的空安全机制
  • 强大的控制流 (if, when, for, while)
  • 灵活的函数定义(默认参数、命名参数)
  • 基础的集合操作 (List, Set, Map)
  • 简单的类和对象创建

这为你使用 Kotlin 进行开发打下了坚实的基础。Kotlin 是一门设计精良且功能丰富的语言,还有很多值得探索的地方:

  • 面向对象编程深入: 继承、接口、抽象类、数据类、枚举类、密封类、对象声明等。
  • 函数式编程: Lambda 表达式、高阶函数、集合操作符(map, filter, reduce 等)。
  • 协程 (Coroutines): Kotlin 官方推荐的异步编程解决方案,用于简化并发和非阻塞代码。
  • Kotlin 标准库: 探索更多实用的工具函数和扩展函数。
  • 特定平台开发:
    • Android 开发: 学习 Jetpack Compose (UI), ViewModel, LiveData/Flow, Room 等。
    • 服务器端开发: 学习 Ktor, Spring Boot with Kotlin 等框架。
    • Kotlin Multiplatform: 探索如何在不同平台(iOS, Android, Web, Desktop)间共享代码。

推荐资源:

继续实践,多写代码,是掌握 Kotlin 最好的方式。祝你在 Kotlin 的学习旅程中一切顺利!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部