这是一篇 Kotlin 快速入门笔记,适合有 JS / TS 基础的开发者阅读。文章通过大量代码示例,梳理 Kotlin 的变量、类型、集合、控制流、函数、Lambda、类和数据类等基础语法,帮助读者快速建立 Kotlin 的语法体系。
1. Kotlin 基础
1.1入口文件
fun main() {
println("Hello, world!")
// Hello, world!
}
1.2变量
| 写法 |
含义 |
类似 JS / TS |
val |
只读变量 |
const |
var |
可变变量 |
let |
String? |
可空变量 |
`string |
lateinit var |
延迟初始化变量 |
先声明后赋值 |
const val |
编译期常量 |
真正常量 |
val xxx by lazy |
懒加载变量 |
第一次用时初始化 |
fun main() {
// 1. val:只读变量,类似 JS / TS 的 const
val name = "Tom"
println(name)
// name = "Jack" // 报错:val 不能重新赋值
// 2. var:可变变量,类似 JS / TS 的 let
var age = 18
age = 20
println(age)
// 3. String?:可空变量,类似 TS 的 string | null
var title: String? = "Kotlin 学习笔记"
title = null
println(title)
// 4. lateinit var:延迟初始化变量,先声明,后赋值
val user = User()
user.username = "Alice"
println(user.username)
// 5. const val:编译期常量
println(API_URL)
// 6. val xxx by lazy:懒加载变量,第一次使用时才初始化
println(config)
println(config)
}
// lateinit var 通常写在类里面
class User {
lateinit var username: String
}
// const val 必须写在顶层、object 或 companion object 中
const val API_URL = "https://example.com"
// lazy 变量第一次被访问时,才会执行初始化代码
val config: String by lazy {
println("初始化 config")
"这是配置内容"
}
1.3 字符串模板
fun main() {
val name = "Tom"
val age = 18
val price = 99
// 变量插值
println("name = $name")
// 表达式插值
println("next age = ${age + 1}")
// 属性访问
println("name length = ${name.length}")
// 函数调用
println("upper name = ${name.uppercase()}")
// if 表达式
println("type = ${if (age >= 18) "adult" else "child"}")
// 输出 $ 符号
println("price = \$$price")
// 多行字符串
val message = """
name = $name
age = $age
price = ${'$'}$price
""".trimIndent()
println(message)
}
1.4基本数据类型
| 类型 |
含义 |
示例 |
说明 |
Byte |
8 位整数 |
val a: Byte = 127 |
范围:-128 ~ 127 |
Short |
16 位整数 |
val a: Short = 1000 |
范围比 Byte 大 |
Int |
32 位整数 |
val a: Int = 100 |
默认整数类型 |
Long |
64 位整数 |
val a: Long = 100L |
数字后加 L |
Float |
32 位浮点数 |
val a: Float = 3.14F |
数字后加 F 或 f |
Double |
64 位浮点数 |
val a: Double = 3.14 |
默认小数类型 |
Boolean |
布尔值 |
val ok: Boolean = true |
只有 true / false |
Char |
单个字符 |
val c: Char = 'A' |
使用单引号 |
String |
字符串 |
val s: String = "Hello" |
使用双引号 |
Array<T> |
数组 |
val arr = arrayOf(1, 2, 3) |
固定长度,元素类型统一 |
UByte |
无符号 8 位整数 |
val a: UByte = 255u |
范围:0 ~ 255 |
UShort |
无符号 16 位整数 |
val a: UShort = 65535u |
无负数 |
UInt |
无符号 32 位整数 |
val a: UInt = 100u |
数字后加 u |
ULong |
无符号 64 位整数 |
val a: ULong = 100uL |
数字后加 uL |
fun main() {
val age: Int = 18
val money: Long = 100000L
val price: Double = 19.99
val height: Float = 175.5F
val isLogin: Boolean = true
val grade: Char = 'A'
val name: String = "Tom"
val numbers: Array<Int> = arrayOf(1, 2, 3)
println(age)
println(money)
println(price)
println(height)
println(isLogin)
println(grade)
println(name)
println(numbers.contentToString())
}
1.5集合
| 类型 |
含义 |
是否有序 |
是否允许重复 |
是否可修改 |
示例 |
List<T> |
只读列表 |
是 |
是 |
否 |
listOf(1, 2, 3) |
MutableList<T> |
可变列表 |
是 |
是 |
是 |
mutableListOf(1, 2, 3) |
Set<T> |
只读集合 |
通常不关心顺序 |
否 |
否 |
setOf(1, 2, 3) |
MutableSet<T> |
可变集合 |
通常不关心顺序 |
否 |
是 |
mutableSetOf(1, 2, 3) |
Map<K, V> |
只读键值对 |
按实现决定 |
Key 不允许重复 |
否 |
mapOf("a" to 1) |
MutableMap<K, V> |
可变键值对 |
按实现决定 |
Key 不允许重复 |
是 |
mutableMapOf("a" to 1) |
常用操作函数:
| 函数 |
作用 |
示例 |
size |
获取数量 |
list.size |
isEmpty() |
是否为空 |
list.isEmpty() |
contains() |
是否包含元素 |
list.contains("A") |
first() |
第一个元素 |
list.first() |
last() |
最后一个元素 |
list.last() |
get(index) |
根据索引获取 |
list.get(0) |
[index] |
根据索引获取 |
list[0] |
filter {} |
过滤 |
list.filter { it > 10 } |
map {} |
映射转换 |
list.map { it * 2 } |
forEach {} |
遍历 |
list.forEach { println(it) } |
1.6控制流
1.6.1 if && when
| 语法 |
作用 |
是否能返回值 |
适合场景 |
示例形式 |
if |
条件判断 |
是 |
简单二选一判断 |
if (age >= 18) "adult" else "child" |
if else if |
多条件判断 |
是 |
条件数量较少 |
if (...) ... else if (...) ... else ... |
when (value) |
按值匹配 |
是 |
类似 switch,适合多个固定值 |
when (day) { 1 -> ... } |
when 多值匹配 |
多个值走同一分支 |
是 |
多个 case 结果相同 |
1, 2, 3 -> ... |
when 范围匹配 |
判断值是否在范围内 |
是 |
分数、年龄、区间判断 |
in 60..100 -> ... |
when 类型匹配 |
判断变量类型 |
是 |
Any 类型、父类类型判断 |
is String -> ... |
when {} |
不带参数的条件判断 |
是 |
替代复杂 if else if |
when { score >= 90 -> ... } |
fun main() {
val age = 18
val score = 85
val day = 6
val value: Any = "Kotlin"
// 1. if:简单二选一,替代三元表达式
val userType = if (age >= 18) "adult" else "child"
// 2. if else if:多个条件判断
val ageLevel = if (age < 18) {
"未成年"
} else if (age < 60) {
"成年人"
} else {
"老年人"
}
// 3. when(value):按固定值匹配
val dayName = when (day) {
1 -> "Monday"
2 -> "Tuesday"
3 -> "Wednesday"
4 -> "Thursday"
5 -> "Friday"
6, 7 -> "Weekend" // 多个值匹配同一个分支
else -> "Unknown"
}
// 4. when:范围匹配
val scoreLevel = when (score) {
in 90..100 -> "A"
in 80..89 -> "B"
in 60..79 -> "C"
in 0..59 -> "D"
else -> "Invalid"
}
// 5. when:类型匹配
val typeResult = when (value) {
is String -> "String length = ${value.length}"
is Int -> "Int value = $value"
is Boolean -> "Boolean value = $value"
else -> "Unknown type"
}
// 6. when {}:不带参数,类似 if else if
val comment = when {
score >= 90 -> "优秀"
score >= 80 -> "良好"
score >= 60 -> "及格"
else -> "不及格"
}
println(userType)
println(ageLevel)
println(dayName)
println(scoreLevel)
println(typeResult)
println(comment)
}
1.6.2Ranges
| 写法 |
含义 |
是否包含结束值 |
示例 |
结果 / 含义 |
1..5 |
创建闭区间 |
包含 |
1..5 |
1, 2, 3, 4, 5 |
1..<5 |
创建半开区间 |
不包含 |
1..<5 |
1, 2, 3, 4 |
1 until 5 |
创建半开区间 |
不包含 |
1 until 5 |
1, 2, 3, 4 |
5 downTo 1 |
倒序区间 |
包含 |
5 downTo 1 |
5, 4, 3, 2, 1 |
1..10 step 2 |
指定步长 |
包含 |
1..10 step 2 |
1, 3, 5, 7, 9 |
5 downTo 1 step 2 |
倒序指定步长 |
包含 |
5 downTo 1 step 2 |
5, 3, 1 |
in |
判断是否在范围内 |
- |
3 in 1..5 |
true |
!in |
判断是否不在范围内 |
- |
6 !in 1..5 |
true |
'a'..'z' |
字符范围 |
包含 |
'c' in 'a'..'z' |
true |
array.indices |
数组 / 集合索引范围 |
包含 |
list.indices |
0..最后一个索引 |
fun main() {
// 1. 闭区间:包含结束值
for (i in 1..5) {
print("$i ")
}
println()
// 输出:1 2 3 4 5
// 2. 半开区间:不包含结束值
for (i in 1..<5) {
print("$i ")
}
println()
// 输出:1 2 3 4
// 3. until:也是半开区间,不包含结束值
for (i in 1 until 5) {
print("$i ")
}
println()
// 输出:1 2 3 4
// 4. downTo:倒序
for (i in 5 downTo 1) {
print("$i ")
}
println()
// 输出:5 4 3 2 1
// 5. step:指定步长
for (i in 1..10 step 2) {
print("$i ")
}
println()
// 输出:1 3 5 7 9
// 6. downTo + step:倒序指定步长
for (i in 10 downTo 1 step 3) {
print("$i ")
}
println()
// 输出:10 7 4 1
// 7. in:判断是否在范围内
val age = 18
if (age in 18..60) {
println("成年人")
}
// 8. !in:判断是否不在范围内
val score = 120
if (score !in 0..100) {
println("分数非法")
}
// 9. Char 范围
val char = 'k'
if (char in 'a'..'z') {
println("小写字母")
}
// 10. indices:遍历集合索引
val names = listOf("Tom", "Alice", "Jack")
for (index in names.indices) {
println("index = $index, value = ${names[index]}")
}
}
1.6.3Loops
| 语法 |
含义 |
是否先判断条件 |
适合场景 |
示例 |
for (item in collection) |
遍历集合元素 |
是 |
遍历 List、Set、Array |
for (name in names) |
for (i in range) |
遍历范围 |
是 |
固定次数循环 |
for (i in 1..5) |
for (i in collection.indices) |
遍历索引 |
是 |
需要索引访问元素 |
for (i in list.indices) |
for ((index, value) in list.withIndex()) |
同时拿索引和值 |
是 |
需要索引和值 |
for ((i, v) in list.withIndex()) |
while (condition) |
条件循环 |
是 |
不确定循环次数 |
while (count < 5) |
do { } while (condition) |
先执行一次再判断 |
否 |
至少执行一次 |
do { ... } while (...) |
break |
退出循环 |
- |
满足条件时停止循环 |
break |
continue |
跳过本次循环 |
- |
跳过当前项,继续下一次 |
continue |
fun main() {
// 1. for:遍历集合元素
val names = listOf("Tom", "Alice", "Jack")
for (name in names) {
println(name)
}
// 2. for:遍历范围
for (i in 1..5) {
println("i = $i")
}
// 3. for:半开区间,不包含结束值
for (i in 0 until 5) {
println("index = $i")
}
// 4. for:倒序遍历
for (i in 5 downTo 1) {
println("倒序 i = $i")
}
// 5. for:指定步长
for (i in 1..10 step 2) {
println("step i = $i")
}
// 6. for:遍历集合索引
for (index in names.indices) {
println("index = $index, value = ${names[index]}")
}
// 7. for:同时获取索引和值
for ((index, value) in names.withIndex()) {
println("index = $index, value = $value")
}
// 8. while:先判断条件,再执行
var count = 0
while (count < 3) {
println("while count = $count")
count++
}
// 9. do while:先执行一次,再判断条件
var num = 0
do {
println("do while num = $num")
num++
} while (num < 3)
// 10. break:退出循环
for (i in 1..10) {
if (i == 5) {
break
}
println("break 示例 i = $i")
}
// 11. continue:跳过本次循环
for (i in 1..5) {
if (i == 3) {
continue
}
println("continue 示例 i = $i")
}
}
1.7函数
| 类型 |
写法 |
含义 |
适合场景 |
| 普通函数 |
fun name() {} |
定义一个函数 |
复用一段逻辑 |
| 带参数函数 |
fun add(a: Int, b: Int) |
函数接收参数 |
需要外部传值 |
| 带返回值函数 |
fun add(...): Int |
指定返回类型 |
计算并返回结果 |
Unit 返回值 |
fun log(): Unit |
没有实际返回值 |
类似 JS 的 void |
| 单表达式函数 |
fun add(a: Int, b: Int) = a + b |
简化函数写法 |
函数体只有一行表达式 |
| 默认参数 |
fun hello(name: String = "Tom") |
参数有默认值 |
调用时可省略参数 |
| 命名参数 |
hello(name = "Alice") |
调用时指定参数名 |
提高可读性 |
| 可变参数 |
vararg nums: Int |
接收多个同类型参数 |
参数数量不固定 |
| Lambda |
{ x: Int -> x * 2 } |
匿名函数表达式 |
临时传递逻辑 |
| 函数类型 |
(Int) -> Int |
表示函数的类型 |
函数作为变量 / 参数 |
| 高阶函数 |
fun calc(action: () -> Unit) |
参数或返回值是函数 |
回调、集合操作 |
| trailing lambda |
repeat(3) { ... } |
最后一个参数是 Lambda 时可放到括号外 |
Kotlin 常见写法 |
it 简写 |
{ it * 2 } |
单参数 Lambda 的默认参数名 |
简化单参数 Lambda |
fun main() {
// 1. 普通函数
sayHello()
// 2. 带参数函数
greet("Tom")
// 3. 带返回值函数
val sum = add(10, 20)
println(sum)
// 4. 单表达式函数
println(multiply(3, 4))
// 5. 默认参数
hello()
hello("Alice")
// 6. 命名参数
createUser(name = "Jack", age = 18)
// 7. 可变参数 vararg
println(sumAll(1, 2, 3, 4, 5))
// 8. Lambda:赋值给变量
val double: (Int) -> Int = { x: Int -> x * 2 }
println(double(10))
// 9. Lambda:单参数时可以用 it
val triple: (Int) -> Int = { it * 3 }
println(triple(10))
// 10. 高阶函数:函数作为参数
runTask {
println("执行任务")
}
// 11. 自定义高阶函数
val result = calculate(10, 20) { a, b ->
a + b
}
println(result)
// 12. 集合中常见 Lambda
val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }
val doubleNumbers = numbers.map { it * 2 }
println(evenNumbers)
println(doubleNumbers)
}
// 普通函数
fun sayHello() {
println("Hello Kotlin")
}
// 带参数函数
fun greet(name: String) {
println("Hello, $name")
}
// 带返回值函数
fun add(a: Int, b: Int): Int {
return a + b
}
// 单表达式函数
fun multiply(a: Int, b: Int): Int = a * b
// 返回 Unit,Unit 可以省略
fun log(message: String): Unit {
println(message)
}
// 默认参数
fun hello(name: String = "Tom") {
println("Hello, $name")
}
// 命名参数示例
fun createUser(name: String, age: Int) {
println("name = $name, age = $age")
}
// 可变参数
fun sumAll(vararg numbers: Int): Int {
var result = 0
for (number in numbers) {
result += number
}
return result
}
// 高阶函数:参数是一个函数
fun runTask(task: () -> Unit) {
println("任务开始")
task()
println("任务结束")
}
// 高阶函数:接收两个 Int 和一个 Lambda
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
1.7.1扩展函数
| 内容 |
写法 |
含义 |
适合场景 |
| 扩展函数 |
fun String.xxx() |
给已有类型“增加函数” |
不改源码的情况下扩展能力 |
| 接收者类型 |
String / Int / User |
被扩展的类型 |
决定这个函数能被谁调用 |
| 接收者对象 |
this |
当前调用扩展函数的对象 |
在函数内部访问调用者 |
| 可空类型扩展 |
fun String?.xxx() |
给可空类型扩展函数 |
统一处理 null |
| 泛型扩展函数 |
fun <T> List<T>.xxx() |
给泛型类型扩展函数 |
扩展集合类能力 |
| 扩展属性 |
val String.xxx: Int |
给已有类型增加“属性” |
只读计算属性 |
| 作用范围 |
当前文件 / import 后可用 |
不是全局自动生效 |
需要在使用处能访问到 |
| 本质 |
静态函数 |
不是修改原类 |
编译后类似工具函数 |
fun main() {
// 1. 给 String 扩展函数
val text = "hello"
println(text.addPrefix())
println(text.firstChar())
// 2. this 表示当前调用者
val name = "Tom"
println(name.sayHello())
// 3. 给可空类型扩展函数
val title1: String? = "Kotlin"
val title2: String? = null
println(title1.orDefault())
println(title2.orDefault())
// 4. 给自定义类型扩展函数
val user = User("Alice", 20)
println(user.displayInfo())
// 5. 给集合扩展函数
val numbers = listOf(1, 2, 3, 4, 5)
println(numbers.secondOrNull())
println(numbers.joinWithDash())
// 6. 扩展属性
println(text.lastIndex)
}
// 1. String 扩展函数
fun String.addPrefix(): String {
return "Text: $this"
}
// 单表达式写法
fun String.firstChar(): Char {
return this[0]
}
// 2. this 表示当前调用扩展函数的对象
fun String.sayHello(): String {
return "Hello, $this"
}
// 3. 可空类型扩展函数
fun String?.orDefault(): String {
return this ?: "默认值"
}
// 4. 自定义类型
data class User(
val name: String,
val age: Int
)
fun User.displayInfo(): String {
return "name = $name, age = $age"
}
// 5. 泛型集合扩展函数
fun <T> List<T>.secondOrNull(): T? {
return if (this.size >= 2) this[1] else null
}
fun List<Int>.joinWithDash(): String {
return this.joinToString("-")
}
// 6. 扩展属性
val String.lastIndex: Int
get() = this.length - 1
1.7.2带接收器的lambda表达式
| 写法 |
含义 |
类似理解 |
(T) -> R |
普通 lambda,T 是参数 |
JS 里的 (obj) => result |
T.() -> R |
带接收者的 lambda,T 是 this |
在 T 的上下文里执行代码 |
Canvas.() -> Unit |
lambda 内部的 this 是 Canvas |
可以直接调用 Canvas 的方法 |
MutableList<Int>.() -> Unit |
lambda 内部的 this 是 MutableList<Int> |
可以直接 add(...) |
StringBuilder.() -> Unit |
lambda 内部的 this 是 StringBuilder |
可以直接 append(...) |
T.(A) -> R |
既有接收者 T,又有普通参数 A |
this 是 T,同时还能接收参数 |
this.xxx |
显式访问接收者对象 |
this.drawCircle() |
xxx |
省略 this 后的写法 |
drawCircle() |
class Canvas {
fun drawCircle() {
println("Drawing circle")
}
fun drawSquare() {
println("Drawing square")
}
}
// block 的类型是 Canvas.() -> Unit
// 表示这个 lambda 执行时,内部的 this 是 Canvas
fun render(block: Canvas.() -> Unit) {
val canvas = Canvas()
// 等价于 block(canvas)
// 但因为 block 是带接收者的 lambda,所以写成 canvas.block()
canvas.block()
}
fun main() {
render {
// 这里的 this 是 Canvas
drawCircle()
drawSquare()
// 等价于:
// this.drawCircle()
// this.drawSquare()
}
}
1.8类
| 类型 |
写法 |
含义 |
适合场景 |
| 普通类 |
class User |
定义一个类 |
需要封装属性和行为 |
| 主构造函数 |
class User(val name: String) |
类名后面的构造函数 |
创建对象时传入参数 |
| 成员属性 |
val name: String / var age: Int |
对象上的属性 |
保存对象状态 |
| 成员方法 |
fun sayHello() |
类里面的函数 |
定义对象行为 |
init 块 |
init {} |
初始化代码块 |
构造对象时执行额外逻辑 |
| 普通构造参数 |
class User(name: String) |
只是参数,不是属性 |
只在初始化阶段使用 |
| 只读属性参数 |
class User(val name: String) |
构造参数 + 只读属性 |
创建后可访问,不可修改 |
| 可变属性参数 |
class User(var name: String) |
构造参数 + 可变属性 |
创建后可访问,可修改 |
| 数据类 |
data class User(...) |
专门表示数据的类 |
DTO、接口返回值、状态对象 |
copy() |
user.copy(age = 20) |
复制对象并修改部分字段 |
创建新对象 |
| 解构声明 |
val (name, age) = user |
拆出数据类属性 |
快速取值 |
| 自动生成方法 |
toString() / equals() / hashCode() |
数据类自动生成 |
比较、打印、集合操作 |
fun main() {
// 1. 普通类:需要自己定义属性和方法
val user = User("Tom", 18)
println(user.name)
println(user.age)
user.age = 20
println(user.age)
user.sayHello()
// 2. 构造参数不加 val / var:只是参数,不是对象属性
val product = Product("Phone", 3999.0)
println(product.displayName)
println(product.isExpensive)
// println(product.name) // 报错:name 不是属性
// println(product.price) // 报错:price 不是属性
// 3. 数据类:主要用来存数据
val person1 = Person("Alice", 20)
val person2 = Person("Alice", 20)
// data class 自动生成 toString()
println(person1)
// data class 自动生成 equals()
println(person1 == person2) // true
// 4. copy:复制对象,并修改部分字段
val person3 = person1.copy(age = 21)
println(person3)
// 5. 解构声明
val (name, age) = person1
println(name)
println(age)
}
// 普通类
class User(
val name: String, // 只读属性
var age: Int // 可变属性
) {
init {
println("User 被创建了:$name, $age")
}
fun sayHello() {
println("Hello, my name is $name")
}
}
// 构造参数没有 val / var,只能在初始化阶段使用
class Product(name: String, price: Double) {
val displayName = "商品名称:$name"
val isExpensive = price > 1000
init {
println("创建商品:$name, 价格:$price")
}
}
// 数据类
data class Person(
val name: String,
val age: Int
)
1.8.1类继承 && 抽象类 && 接口
| 概念 |
写法 |
含义 |
关键点 |
| 普通类 |
class User |
定义一个类 |
默认不能被继承 |
| 可继承类 |
open class Animal |
允许其他类继承 |
Kotlin 类默认是 final |
| 继承类 |
class Dog : Animal() |
Dog 继承 Animal |
父类有构造函数时要调用 |
| 抽象类 |
abstract class Product |
不能直接创建对象,只能被继承 |
可以有普通方法,也可以有抽象方法 |
| 抽象属性 |
abstract val category: String |
子类必须实现的属性 |
子类用 override 实现 |
| 抽象方法 |
abstract fun work() |
子类必须实现的方法 |
没有方法体 |
| 接口 |
interface Flyable |
定义一种能力或规范 |
不能有构造函数 |
| 实现接口 |
class Bird : Flyable |
类实现接口能力 |
接口后面没有 () |
| 多接口实现 |
class Bird : Flyable, Runnable |
一个类可以实现多个接口 |
Kotlin 类只能单继承,但接口可以多个 |
| 重写成员 |
override fun play() |
实现或覆盖父级成员 |
Kotlin 必须显式写 override |
| 接口委托 |
class A(b: B) : I by b |
把接口实现交给另一个对象 |
可以减少手动转发代码 |
| 顶层父类 |
Any |
Kotlin 所有类最终都继承自它 |
类似 Java Object |
// 抽象类:表示“是什么”
abstract class Animal(
val name: String
) {
// 抽象属性:子类必须实现
abstract val type: String
// 抽象方法:子类必须实现
abstract fun makeSound()
// 普通方法:子类可以直接复用
fun info() {
println("$name is a $type")
}
}
// 接口:表示“能做什么”
interface Runnable {
fun run()
}
interface Flyable {
fun fly()
}
// Dog 继承 Animal,并实现 Runnable 接口
class Dog(name: String) : Animal(name), Runnable {
override val type: String = "Dog"
override fun makeSound() {
println("$name says: Woof!")
}
override fun run() {
println("$name is running")
}
}
// Bird 继承 Animal,并实现 Runnable 和 Flyable 两个接口
class Bird(name: String) : Animal(name), Runnable, Flyable {
override val type: String = "Bird"
override fun makeSound() {
println("$name says: Tweet!")
}
override fun run() {
println("$name is running")
}
override fun fly() {
println("$name is flying")
}
}
fun main() {
val dog = Dog("Buddy")
dog.info()
dog.makeSound()
dog.run()
val bird = Bird("Sky")
bird.info()
bird.makeSound()
bird.run()
bird.fly()
}
1.8.2 Objects
| 类型 |
写法 |
含义 |
常见用途 |
类似 JS / TS |
| 对象声明 |
object AppConfig { ... } |
定义一个单例对象 |
全局配置、工具对象、共享状态 |
单例对象 / module object |
| 伴生对象 |
companion object { ... } |
绑定在类上的单例对象 |
工厂方法、常量、模拟静态方法 |
static 方法/属性 |
| 对象表达式 |
object : Interface { ... } |
创建匿名对象 |
临时实现接口、回调对象 |
匿名对象 / inline object |
| 数据对象 |
data object Loading |
带更好 toString() / 相等语义的单例 |
sealed 状态、固定状态值 |
enum-like singleton |
| 对象继承接口 |
object X : SomeInterface |
单例对象实现接口 |
默认实现、全局处理器 |
singleton implements interface |
// 1. 单例对象:全局配置
object AppConfig {
const val APP_NAME = "KotlinDemo"
fun printConfig() {
println("App name: $APP_NAME")
}
}
// 2. 类 + companion object:工厂方法
class User private constructor(
val name: String
) {
companion object {
fun create(name: String): User {
return User(name)
}
}
}
// 3. 接口
interface Logger {
fun log(message: String)
}
// 4. object expression:临时实现接口
fun runTask(logger: Logger) {
logger.log("Task started")
}
// 5. data object:固定状态
sealed interface TaskState
data object Idle : TaskState
data object Loading : TaskState
data class Finished(val result: String) : TaskState
fun main() {
AppConfig.printConfig()
val user = User.create("Tom")
println(user.name)
runTask(object : Logger {
override fun log(message: String) {
println("[LOG] $message")
}
})
val state: TaskState = Finished("OK")
when (state) {
Idle -> println("Idle")
Loading -> println("Loading")
is Finished -> println("Finished: ${state.result}")
}
}
1.9作用域函数
| 函数 |
对象引用 |
返回值 |
主要用途 |
常见场景 |
let |
it |
Lambda 最后一行结果 |
转换结果、处理可空对象 |
xxx?.let { ... } |
run |
this |
Lambda 最后一行结果 |
在对象作用域内计算结果 |
初始化后返回计算值 |
with |
this |
Lambda 最后一行结果 |
对已有对象连续操作 |
不需要链式调用时 |
apply |
this |
原对象本身 |
配置对象属性 |
创建对象后初始化属性 |
also |
it |
原对象本身 |
附加操作、副作用 |
打日志、调试、额外处理 |
fun main() {
val user = User("Tom", 18)
// 1. let:常用于可空对象处理,返回 Lambda 最后一行结果
val nameLength = user.name.let {
println("name = $it")
it.length
}
println(nameLength)
// 2. run:this 指向当前对象,返回 Lambda 最后一行结果
val description = user.run {
"name = $name, age = $age"
}
println(description)
// 3. with:不是扩展函数,适合对已有对象做多次操作
val info = with(user) {
println("访问 name = $name")
println("访问 age = $age")
"User($name, $age)"
}
println(info)
// 4. apply:返回原对象,常用于对象初始化
val newUser = User("Alice", 20).apply {
age = 21
city = "Shanghai"
}
println(newUser)
// 5. also:返回原对象,常用于日志、调试、额外操作
val resultUser = User("Jack", 30).also {
println("创建了用户:$it")
}
println(resultUser)
// 6. 可空对象常见写法
val nullableName: String? = "Kotlin"
nullableName?.let {
println("字符串不为空,长度 = ${it.length}")
}
// 7. 链式调用示例
val finalUser = User("Bob", 25)
.also {
println("初始化前:$it")
}
.apply {
age = 26
city = "Beijing"
}
.also {
println("初始化后:$it")
}
println(finalUser)
}
data class User(
var name: String,
var age: Int,
var city: String = ""
)