0%

Kotlin

语法树

graph LR
    A[Kotlin 语法概览]

    %% 1. 基础语法特性
    A --> B[基础语法特性]
    B --> B1[基本数据类型]
    B1 --> B1a["整型: Byte, Short, Int, Long"]
    B1 --> B1b["浮点型: Float, Double"]
    B1 --> B1c["字符型: Char"]
    B1 --> B1d["布尔型: Boolean"]
    
    B --> B2[变量与常量]
    B2 --> B2a["变量: var"]
    B2 --> B2b["常量: val"]
    
    B --> B3[运算符]
    B3 --> B3a["算术运算符: +, -, *, /, %"]
    B3 --> B3b["关系运算符: ==, !=, <, >, <=, >="]
    B3 --> B3c["逻辑运算符: &&, ||, !"]
    B3 --> B3d["位运算符: and, or, xor, shl, shr"]
    B3 --> B3e["赋值运算符: =, +=, -=, *=, /="]
    B3 --> B3f["其他: Elvis ?:, Safe Call ?., !!, in"]
    
    B --> B4[控制结构]
    B4 --> B4a["条件语句: if, else"]
    B4 --> B4b["分支语句: when"]
    B4 --> B4c["循环: for, while, do-while"]
    B4 --> B4d["跳转: break, continue, return"]
    
    B --> B5[函数]
    B5 --> B5a["函数定义: fun"]
    B5 --> B5b["参数: 默认参数, 可变参数 vararg"]
    B5 --> B5c["单表达式函数: ="]
    B5 --> B5d["匿名函数"]
    B5 --> B5e["高阶函数"]
    
    B --> B6[类与对象]
    B6 --> B6a["类定义: class"]
    B6 --> B6b["构造函数: constructor"]
    B6 --> B6c["属性: var, val"]
    B6 --> B6d["访问控制: public, private, protected, internal"]
    B6 --> B6e["继承: open, :"]
    B6 --> B6f["接口: interface"]
    B6 --> B6g["抽象类: abstract"]
    B6 --> B6h["数据类: data"]
    B6 --> B6i["对象声明: object"]
    B6 --> B6j["伴生对象: companion object"]
    
    B --> B7[包与导入]
    B7 --> B7a["包定义: package"]
    B7 --> B7b["导入: import"]
    
    B --> B8[异常处理]
    B8 --> B8a["try, catch, finally"]
    B8 --> B8b["throw"]
    
    B --> B9[泛型]
    B9 --> B9a["泛型类: <T>"]
    B9 --> B9b["泛型函数"]
    B9 --> B9c["协变: out"]
    B9 --> B9d["逆变: in"]
    B9 --> B9e["通配符: *"]
    
	B --> B10[空安全]
    B10 --> B10a["可空类型: ?"]
    B10 --> B10b["安全调用: ?."]
    B10 --> B10c["Elvis 操作符: ?:"]
    B10 --> B10d["非空断言: !!"]
    
    B --> B11[注解]
    B11 --> B11a["内置注解: @Deprecated, @Suppress"]
    B11 --> B11b["自定义注解: annotation"]

    %% 2. 现代 Kotlin 新特性
    A --> C[现代 Kotlin 新特性]
    
    C --> C1[Kotlin 1.0+]
    C1 --> C1a["Lambda 表达式: { x -> x * 2 }"]
    C1 --> C1b["扩展函数"]
    C1 --> C1c["中缀函数: infix"]
    C1 --> C1d["运算符重载: operator"]
    
    C --> C2[Kotlin 1.1]
    C2 --> C2a["协程: suspend, launch"]
    
    C --> C3[Kotlin 1.3]
    C3 --> C3a["内联类: inline class"]
    C3 --> C3b["无符号整数: UInt, ULong"]
    
    C --> C4[Kotlin 1.4]
    C4 --> C4a["SAM 转换改进"]
    C4 --> C4b["尾随逗号"]
    
    C --> C5[Kotlin 1.5]
    C5 --> C5a["密封接口: sealed interface"]
    C5 --> C5b["内联值类: value class"]
    
    C --> C6[Kotlin 1.6]
    C6 --> C6a["挂起函数类型: suspend () -> Unit"]
    
    C --> C7[Kotlin 1.8]
    C7 --> C7a["上下文接收者: context"]
    
    C --> C8[Kotlin 1.9+]
    C8 --> C8a["多平台改进"]
    C8 --> C8b["K2 编译器特性"]

    %% 3. 其他特性
    A --> D[其他特性]
    D --> D1[标准库扩展]
    D1 --> D1a["集合: List, Set, Map"]
    D1 --> D1b["字符串: String, StringBuilder"]
    D1 --> D1c["IO: java.io"]
    D1 --> D1d["并发: kotlin.coroutines"]
    
    D --> D2[反射与运行时]
    D2 --> D2a["类引用: ::class"]
    D2 --> D2b["函数引用: ::function"]
    D2 --> D2c["反射库: kotlin.reflect"]
    
    D --> D3[委托]
    D3 --> D3a["属性委托: by lazy, by Delegates"]
    D3 --> D3b["类委托: by"]

详解

一、基础语法特性

1. 基本数据类型

1.1 整型:Byte, Short, Int, Long

  • 语法说明
    • Byte:8 位有符号整数,范围 -128127,显式声明为 Byte
    • Short:16 位有符号整数,范围 -3276832767,显式声明为 Short
    • Int:32 位有符号整数,范围 -2,147,483,6482,147,483,647,默认整数类型。
    • Long:64 位有符号整数,范围 -9,223,372,036,854,775,8089,223,372,036,854,775,807,需加 L 后缀。
    • 支持类型推断,如 val x = 42 推断为 Int
  • 应用场景
    • Byte:节省内存,适用于小型数据(如网络协议中的标志位、图像像素值)。
    • Short:较少使用,适用于特定硬件接口或与旧系统交互。
    • Int:日常计数、数组索引、循环变量。
    • Long:大范围数据,如时间戳(毫秒)、文件大小、数据库 ID。
  • 底层原理
    • 在 JVM 上,分别映射为 Java 的 byteshortintlong,为原始类型以优化性能。
    • 当声明为可空类型(如 Int?)或用于泛型时,装箱为 java.lang.ByteShortIntegerLong
    • 编译器优化字面量,例如 val x = 42 使用 int,避免不必要的对象创建。
    • 类型转换需显式调用方法(如 toInt()),避免隐式转换错误。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fun main() {
val byte: Byte = 127
val short: Short = 32_767
val int: Int = 2_147_483_647
val long: Long = 9_223_372_036_854_775_807L
println("Byte: $byte, Short: $short, Int: $int, Long: $long")

// 类型转换
val byteToInt: Int = byte.toInt()
println("Byte to Int: $byteToInt") // 127

// 溢出示例
val overflow: Byte = (byte + 1).toByte() // 127 + 1 = -128(溢出)
println("Overflow Byte: $overflow")

// 可空类型
val nullableLong: Long? = null
println("Nullable Long: $nullableLong")
}
  • 注意事项
    • 溢出风险ByteShort 操作超出范围不会自动提升类型,需手动转换(如 (byte + 1).toByte()),否则溢出(如 127 + 1 = -128)。
    • 类型转换:必须显式转换(如 toInt()),否则编译错误,避免隐式转换导致的意外。
    • 性能:优先使用 Int,因为它是 JVM 的默认整数类型,ByteShort 在某些场景可能因装箱而降低性能。
    • L 后缀Long 字面量忘记加 L 会默认推断为 Int,可能导致溢出。

1.2 浮点型:Float, Double

  • 语法说明
    • Float:32 位单精度浮点数,约 6-7 位有效数字,需加 fF 后缀(如 3.14f)。
    • Double:64 位双精度浮点数,约 15-16 位有效数字,默认浮点类型(如 3.14)。
    • 支持科学计数法(如 1.23e-4)。
  • 应用场景
    • Float:节省内存,适用于图形渲染(如 OpenGL 坐标)、低精度计算。
    • Double:高精度计算,如科学计算、财务数据处理、地理坐标。
  • 底层原理
    • 遵循 IEEE 754 标准,包含 1 位符号、指数位(Float 8 位,Double 11 位)和尾数位(Float 23 位,Double 52 位)。
    • 在 JVM 上,Float 映射为 floatDouble 映射为 double,可空时装箱为 java.lang.FloatDouble
    • 运算结果可能因舍入而有微小误差。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fun main() {
val float: Float = 3.14159f
val double: Double = 3.141592653589793
println("Float: $float, Double: $double")

// 科学计数法
val sciFloat: Float = 1.23e2f // 123.0
println("Scientific Float: $sciFloat")

// 精度问题
val sumFloat = 0.1f + 0.2f
println("Float 0.1 + 0.2 = $sumFloat") // 0.300000004(误差)
val sumDouble = 0.1 + 0.2
println("Double 0.1 + 0.2 = $sumDouble") // 0.30000000000000004(更高精度)

// 类型转换
val floatToDouble: Double = float.toDouble()
println("Float to Double: $floatToDouble")
}
  • 注意事项
    • 精度问题:浮点运算可能有舍入误差(如 0.1 + 0.2 != 0.3),避免直接用 == 比较,建议用范围检查(如 abs(a - b) < 0.0001)。
    • f 后缀Float 字面量忘记加 f 会推断为 Double,导致类型不匹配。
    • 性能与内存Float 节省内存,但精度低,Double 更适合高精度需求。
    • 溢出与无穷:除以 0 返回 Infinity 而非异常,需检查结果。

1.3 字符型:Char

  • 语法说明
    • 表示 16 位 Unicode 字符,使用单引号定义(如 'A')。
    • 支持转义字符(如 \n, \t)和 Unicode 码点(如 \u0041 表示 'A')。
  • 应用场景
    • 文本解析(如逐字符处理字符串)。
    • 表示单个按键输入或编码转换。
  • 底层原理
    • 映射到 JVM 的 char,存储为 16 位无符号整数(0 到 65535)。
    • 可空时装箱为 java.lang.Character
    • 支持与整数运算,基于 Unicode 码点。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun main() {
val char: Char = 'K'
val unicodeChar: Char = '\u004B' // 'K'
println("Char: $char, Unicode: $unicodeChar, Code: ${char.code}") // K, K, 75

// 转义字符
val newline: Char = '\n'
print("Line1${newline}Line2") // Line1换行Line2

// 字符运算
val nextChar = char + 1 // 'L'
println("Next Char: $nextChar") // L

// 可空类型
val nullableChar: Char? = null
println("Nullable Char: $nullableChar")
}
  • 注意事项
    • 与数字区分Char 不能直接当作整数使用,需用 .code 转换。
    • 单引号:使用双引号(如 "A")会推断为 String,导致类型错误。
    • 范围限制:超出 Unicode 范围(如 \uFFFF 以上)无效。
    • 运算结果Char 加减返回 Int,需转换回 Char

1.4 布尔型:Boolean

  • 语法说明
    • 表示 truefalse,用于逻辑判断。
    • 可声明为可空类型(如 Boolean?)。
  • 应用场景
    • 条件判断(如 if 语句)。
    • 状态标志(如 isActive)。
    • 三态逻辑(true, false, null)。
  • 底层原理
    • 映射到 JVM 的 boolean,占用 1 位(实际实现可能占 1 字节)。
    • 可空时装箱为 java.lang.Boolean
    • 逻辑运算基于短路求值。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun main() {
val isActive: Boolean = true
val isDone: Boolean? = null
println("isActive: $isActive, isDone: $isDone")

// 逻辑运算
val result = isActive && (isDone ?: false)
println("Result: $result") // false

// 三态逻辑
val status = when (isDone) {
true -> "Completed"
false -> "Pending"
null -> "Unknown"
}
println("Status: $status") // Unknown
}
  • 注意事项
    • 可空处理Boolean? 在逻辑运算中需配合 ?:!!,否则编译错误。
    • 短路求值&&|| 是短路的,避免在右边放入副作用代码。
    • 性能:避免不必要的装箱(如 Boolean?),影响效率。

2. 变量与常量

2.1 变量:var

  • 语法说明
    • 使用 var 关键字声明可变变量,可多次赋值。
    • 支持类型推断(如 var x = 10 推断为 Int),或显式声明(如 var x: Int = 10)。
  • 应用场景
    • 循环计数器、临时状态存储。
    • 用户输入或动态数据处理。
  • 底层原理
    • 编译为 JVM 的普通局部变量或字段,分配内存后可自由修改。
    • 类型推断在编译时完成,生成对应的字节码类型(如 int)。
    • 不涉及运行时开销。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fun main() {
var count = 10
println("Initial: $count") // 10
count = 20
println("Updated: $count") // 20

// 类型显式声明
var name: String = "Kotlin"
name = "Java"
println("Name: $name") // Java

// 作用域示例
run {
var local = 5
local += 1
println("Local: $local") // 6
}
}
  • 注意事项
    • 过度使用:滥用 var 增加可变性,降低代码安全性,建议优先用 val
    • 类型一致性:赋值时类型必须匹配,否则编译错误。
    • 作用域:局部变量未初始化不会报错,但使用前需赋值。

2.2 常量:val

  • 语法说明
    • 使用 val 关键字声明只读变量,赋值后不可更改引用。
    • 支持类型推断和显式声明。
    • 可用于表达式返回值。
  • 应用场景
    • 常量定义(如数学常数 PI)。
    • 函数结果缓存、不可变配置。
  • 底层原理
    • 编译为 JVM 的 final 变量,确保引用不可变。
    • 对于对象,val 只限制引用,对象内部状态可通过方法修改。
    • 若为基本类型,编译器可能内联值以优化性能。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fun main() {
val pi = 3.14
// pi = 3.15 // 错误:val 不可重新赋值
println("Pi: $pi")

// 可变对象
val list = mutableListOf(1, 2)
list.add(3)
println("List: $list") // [1, 2, 3]

// 表达式赋值
val x = 5
val max = if (x > 0) x else 0
println("Max: $max") // 5
}
  • 注意事项
    • 引用 vs 对象val 只限制引用,对象内容可变,需区分。
    • 初始化:必须初始化或在 init 块中赋值,否则编译错误。
    • 性能:编译器可能内联 val,但复杂表达式不会。

3. 运算符

3.1 算术运算符:+, -, *, /, %

  • 语法说明
    • +:加法或字符串拼接。
    • -:减法。
    • *:乘法。
    • /:除法(整数除法结果为整数,浮点除法为浮点数)。
    • %:取模。
  • 应用场景
    • 数学计算(如统计、物理模拟)。
    • 字符串拼接(如日志生成)。
  • 底层原理
    • 映射到 JVM 的数学指令(如 iadd, fdiv)。
    • 字符串 + 编译为 StringBuilder 操作。
    • 除法对整数和浮点分开处理。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
fun main() {
val a = 10
val b = 3
println("a + b = ${a + b}") // 13
println("a - b = ${a - b}") // 7
println("a * b = ${a * b}") // 30
println("a / b = ${a / b}") // 3 (整数除法)
println("a % b = ${a % b}") // 1
println("Hello " + "World") // Hello World
}
  • 注意事项
    • 除以零:整数除以 0 抛 ArithmeticException,浮点返回 Infinity
    • 类型提升:操作数类型不同时提升到更高精度(如 Int + Double 结果为 Double)。
    • 字符串拼接性能:大量 + 操作效率低,建议用模板或 StringBuilder

3.2 关系运算符:==, !=, <, >, <=, >=

  • 语法说明
    • ==:值相等。
    • !=:值不等。
    • <, >:小于、大于。
    • <=, >=:小于等于、大于等于。
    • ===, !==:引用相等/不等。
  • 应用场景
    • 条件判断、排序算法。
  • 底层原理
    • == 调用 equals()=== 检查对象引用。
    • 其他运算符映射到 JVM 比较指令(如 if_icmplt)。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
fun main() {
val x = 5
val y = 10
println("x == y: ${x == y}") // false
println("x < y: ${x < y}") // true

val str1 = "Kotlin"
val str2 = "Kotlin"
println("str1 === str2: ${str1 === str2}") // true (字符串池)
}
  • 注意事项
    • 浮点比较:避免直接用 ==,因精度误差可能导致错误。
    • === 使用:仅适用于对象引用,基本类型始终用 ==
    • 自定义类== 需要重写 equals()

3.3 逻辑运算符:&&, ||, !

  • 语法说明
    • &&:逻辑与,短路求值。
    • ||:逻辑或,短路求值。
    • !:逻辑非。
  • 应用场景
    • 多条件组合判断。
  • 底层原理
    • 短路求值优化性能,映射到 JVM 逻辑指令。
  • 示例代码
1
2
3
4
5
6
7
fun main() {
val a = true
val b = false
println("a && b: ${a && b}") // false
println("a || b: ${a || b}") // true
println("!a: ${!a}") // false
}
  • 注意事项
    • 副作用:短路求值可能跳过右边代码,注意逻辑顺序。
    • 可空类型Boolean? 需处理 null

3.4 位运算符:and, or, xor, shl, shr

  • 语法说明
    • and:按位与。
    • or:按位或。
    • xor:按位异或。
    • shl:左移。
    • shr:右移(带符号)。
  • 应用场景
    • 权限标志、位掩码、低级优化。
  • 底层原理
    • 映射到 JVM 位操作指令(如 iand, ishl)。
  • 示例代码
1
2
3
4
5
6
7
8
9
fun main() {
val x = 5 // 101
val y = 3 // 011
println("x and y: ${x and y}") // 1 (001)
println("x or y: ${x or y}") // 7 (111)
println("x xor y: ${x xor y}") // 6 (110)
println("x shl 1: ${x shl 1}") // 10 (1010)
println("x shr 1: ${x shr 1}") // 2 (010)
}
  • 注意事项
    • 符号位shr 是带符号右移,负数需注意。
    • 溢出:移位不检查范围,可能导致意外结果。

3.5 赋值运算符:=, +=, -=, *=, /=

  • 语法说明
    • =:简单赋值。
    • +=, -=, *=, /=:组合赋值。
  • 应用场景
    • 累加操作、状态更新。
  • 底层原理
    • 编译为赋值和计算的组合指令。
  • 示例代码
1
2
3
4
5
6
7
fun main() {
var x = 10
x += 5
println("x += 5: $x") // 15
x *= 2
println("x *= 2: $x") // 30
}
  • 注意事项
    • 不可变变量val 不支持赋值运算符。
    • 类型匹配:右边类型需与左边兼容。

3.6 其他运算符:?:, ?., !!, in

  • 语法说明
    • ?:(Elvis):若左边为 null,返回右边值。
    • ?.:安全调用,若对象为 null 返回 null
    • !!:非空断言,若为 null 抛异常。
    • in:检查是否在范围或集合中。
  • 应用场景
    • 空安全处理、范围检查。
  • 底层原理
    • 编译器插入 null 检查和跳转逻辑。
  • 示例代码
1
2
3
4
5
6
7
fun main() {
val str: String? = null
println("Safe call: ${str?.length}") // null
println("Elvis: ${str?.length ?: 0}") // 0
println("In range: ${3 in 1..5}") // true
// println(str!!.length) // 抛 NPE
}
  • 注意事项
    • !! 风险:滥用可能抛 NullPointerException,尽量避免。
    • 性能?.?: 增加分支检查,频繁使用可能影响性能。
    • in 范围:范围对象需实现 contains

4. 控制结构

4.1 条件语句:if, else

  • 语法说明
    • 基本形式:if (condition) { ... } else { ... }
    • 可作为表达式,返回值由最后一行决定。
  • 应用场景
    • 简单条件分支、返回值计算。
  • 底层原理
    • 编译为 JVM 的 if 指令(如 ifne),表达式形式生成临时变量。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
fun main() {
val x = 5
val result = if (x > 0) {
println("Positive")
"Positive"
} else if (x == 0) {
"Zero"
} else {
println("Negative")
"Negative"
}
println("Result: $result") // Positive
}
  • 注意事项
    • 完整性:作为表达式时必须有 else,否则编译错误。
    • 嵌套:过多嵌套降低可读性,考虑用 when

4.2 分支语句:when

  • 语法说明
    • 替代 switch,支持多种条件(如值匹配、范围检查、is 类型检查)。
    • 可作为表达式。
  • 应用场景
    • 多条件分支、模式匹配。
  • 底层原理
    • 编译为条件跳转或表查找(类似 switch)。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
fun main() {
val x = 2
val desc = when (x) {
1 -> "One"
2, 3 -> "Two or Three"
in 1..10 -> "In range"
is Int -> "Integer"
else -> "Other"
}
println("Description: $desc") // Two or Three
}
  • 注意事项
    • 覆盖性:作为表达式时需覆盖所有情况或加 else
    • 性能:复杂条件可能生成较多字节码。

4.3 循环:for, while, do-while

  • 语法说明
    • forfor (item in collection/range) { ... },支持范围、步长。
    • whilewhile (condition) { ... }
    • do-whiledo { ... } while (condition)
  • 应用场景
    • 数据遍历、重复执行。
  • 底层原理
    • for 编译为迭代器调用,while 为条件跳转。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
fun main() {
for (i in 1..5 step 2) print("$i ") // 1 3 5
println()
var x = 0
while (x < 3) {
print("$x ")
x++
} // 0 1 2
println()
do {
print("$x ")
x--
} while (x > 0) // 3 2 1
}
  • 注意事项
    • 范围对象for 需可迭代对象。
    • 无限循环while (true) 需确保退出条件。

4.4 跳转:break, continue, return

  • 语法说明
    • break:退出循环。
    • continue:跳到下一次迭代。
    • return:返回函数结果。
    • 支持标签(如 break@label)。
  • 应用场景
    • 控制循环流程。
  • 底层原理
    • 编译为 goto 或返回指令。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
fun main() {
outer@ for (i in 1..3) {
for (j in 1..3) {
if (j == 2) break@outer
print("$i$j ")
}
} // 11
println()
for (i in 1..5) {
if (i == 3) continue
print("$i ") // 1 2 4 5
}
}
  • 注意事项
    • 标签:多重循环需正确使用标签,避免跳错。
    • 可读性:过多跳转降低代码清晰度。

5. 函数

5.1 函数定义:fun

  • 语法说明
    • 格式:fun name(params): ReturnType { ... }
    • 返回类型可选(类型推断)。
  • 应用场景
    • 代码复用、逻辑封装。
  • 底层原理
    • 编译为 JVM 方法,参数和返回值类型静态绑定。
  • 示例代码
1
2
3
4
5
6
fun add(a: Int, b: Int): Int {
return a + b
}
fun main() {
println(add(3, 4)) // 7
}
  • 注意事项
    • 返回类型:复杂函数建议显式声明返回类型。
    • 命名:遵循清晰命名规范。

5.2 参数:默认参数, vararg

  • 语法说明
    • 默认参数:param: Type = defaultValue
    • vararg:可变参数,接收任意数量参数。
  • 应用场景
    • 简化函数调用、可变参数处理。
  • 底层原理
    • 默认参数生成重载方法。
    • vararg 编译为数组参数。
  • 示例代码
1
2
3
4
5
6
7
fun printItems(vararg items: String, prefix: String = ">") {
items.forEach { println("$prefix $it") }
}
fun main() {
printItems("A", "B", prefix = "#") // # A, # B
printItems("X") // > X
}
  • 注意事项
    • 顺序:默认参数应放在 vararg 后。
    • 唯一性:一个函数只能有一个 vararg

5.3 单表达式函数:=

  • 语法说明
    • 使用 = 替代 {}return,适用于简单函数。
  • 应用场景
    • 简洁计算、工具函数。
  • 底层原理
    • 编译为普通方法,表达式直接作为返回值。
  • 示例代码
1
2
3
4
fun multiply(a: Int, b: Int) = a * b
fun main() {
println(multiply(2, 3)) // 6
}
  • 注意事项
    • 可读性:复杂逻辑不适合单表达式。
    • 类型推断:返回值类型需明确。

5.4 匿名函数

  • 语法说明
    • 格式:fun(params) = expression,无函数名。
  • 应用场景
    • 临时逻辑定义、函数变量。
  • 底层原理
    • 编译为函数对象。
  • 示例代码
1
2
3
4
fun main() {
val anon = fun(x: Int) = x * 2
println(anon(5)) // 10
}
  • 注意事项
    • 性能:频繁创建可能增加开销。
    • 使用范围:适合局部使用。

5.5 高阶函数

  • 语法说明
    • 函数参数或返回值为函数类型(如 (Int) -> Int)。
  • 应用场景
    • 回调、函数式编程。
  • 底层原理
    • 编译为函数接口(如 Function1),若加 inline 则内联。
  • 示例代码
1
2
3
4
fun apply(x: Int, op: (Int) -> Int) = op(x)
fun main() {
println(apply(5) { it * 2 }) // 10
}
  • 注意事项
    • 性能:未加 inline 会生成对象,影响效率。
    • 类型复杂性:参数类型需清晰定义。

6. 类与对象

6.1 类定义:class

  • 语法说明
    • 格式:class Name(params) { ... },主构造函数在类头。
  • 应用场景
    • 数据建模、面向对象设计。
  • 底层原理
    • 编译为 JVM 类,构造函数生成 init 块。
  • 示例代码
1
2
3
4
5
6
7
class Person(val name: String) {
fun greet() = println("Hello, $name")
}
fun main() {
val p = Person("Alice")
p.greet() // Hello, Alice
}
  • 注意事项
    • 主构造函数:参数需明确作用(val/var)。

6.2 构造函数:constructor

  • 语法说明
    • 主构造函数在类头,次构造函数使用 constructor
  • 应用场景
    • 对象初始化多样性。
  • 底层原理
    • 次构造函数委托给主构造函数,编译为多个构造方法。
  • 示例代码
1
2
3
4
5
6
7
8
class Person(val name: String) {
constructor(name: String, age: Int) : this(name) {
println("Age: $age")
}
}
fun main() {
Person("Alice", 25) // Age: 25
}
  • 注意事项
    • 委托:次构造函数必须调用主构造函数。
    • 复杂度:过多构造函数降低可读性。

6.3 属性:var, val

  • 语法说明
    • var 定义可变属性,val 定义只读属性。
    • 可自定义 get/set
  • 应用场景
    • 对象状态管理。
  • 底层原理
    • 编译为字段和访问器方法。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
class Box {
var size: Int = 0
get() = field
set(value) {
if (value >= 0) field = value
}
}
fun main() {
val box = Box()
box.size = 5
println(box.size) // 5
}
  • 注意事项
    • 自定义访问器:避免无限递归(如 get() = size)。
    • 初始化:必须初始化或延迟。

6.4 访问控制:public, private, protected, internal

  • 语法说明
    • public:默认,公开。
    • private:类内可见。
    • protected:类及子类可见。
    • internal:模块内可见。
  • 应用场景
    • 封装性控制。
  • 底层原理
    • 编译为 JVM 访问修饰符。
  • 示例代码
1
2
3
4
5
class Example {
private val secret = 42
protected val subclassVisible = "Protected"
internal val moduleVisible = "Internal"
}
  • 注意事项
    • internal:模块定义需明确。
    • 过度限制:影响扩展性。

6.5 继承:open, :

  • 语法说明
    • open 允许继承,: 表示继承关系。
  • 应用场景
    • 类层次设计。
  • 底层原理
    • 编译为 JVM 继承结构。
  • 示例代码
1
2
open class Animal(val name: String)
class Dog(name: String) : Animal(name)
  • 注意事项
    • open 必要性:类默认不可继承。
    • 单一继承:Kotlin 不支持多重继承。

6.6 接口:interface

  • 语法说明
    • 定义方法和属性,使用 override 实现。
  • 应用场景
    • 多态、行为契约。
  • 底层原理
    • 编译为 JVM 接口。
  • 示例代码
1
2
3
4
5
6
interface Flyable {
fun fly()
}
class Bird : Flyable {
override fun fly() = println("Flying")
}
  • 注意事项
    • 实现冲突:多接口需处理方法冲突。
    • 默认实现:避免过度依赖。

6.7 抽象类:abstract

  • 语法说明
    • 使用 abstract 定义抽象成员。
  • 应用场景
    • 提供部分实现。
  • 底层原理
    • 编译为抽象类。
  • 示例代码
1
2
3
4
5
6
abstract class Shape {
abstract fun area(): Double
}
class Circle(val radius: Double) : Shape() {
override fun area() = Math.PI * radius * radius
}
  • 注意事项
    • 抽象成员:必须被子类实现。
    • 实例化:不可直接实例化。

6.8 数据类:data

  • 语法说明
    • 使用 data 自动生成 toString(), equals(), copy() 等。
  • 应用场景
    • DTO、简单数据容器。
  • 底层原理
    • 编译器生成额外方法。
  • 示例代码
1
2
3
4
5
data class User(val id: Int, val name: String)
fun main() {
val user = User(1, "Alice")
println(user.copy(name = "Bob")) // User(id=1, name=Bob)
}
  • 注意事项
    • 主构造函数:至少一个参数。
    • 继承限制:不可被 open

6.9 对象声明:object

  • 语法说明
    • 使用 object 创建单例。
  • 应用场景
    • 单例模式、工具类。
  • 底层原理
    • 编译为静态实例。
  • 示例代码
1
2
3
4
5
6
object Singleton {
fun hello() = println("Hello")
}
fun main() {
Singleton.hello() // Hello
}
  • 注意事项
    • 状态管理:单例需注意线程安全。
    • 滥用:不适合频繁创建的对象。

6.10 伴生对象:companion object

  • 语法说明
    • 在类中使用 companion object 定义静态成员。
  • 应用场景
    • 工厂方法、静态工具。
  • 底层原理
    • 编译为类的静态字段。
  • 示例代码
1
2
3
4
5
6
7
8
class MyClass {
companion object {
fun create() = MyClass()
}
}
fun main() {
val instance = MyClass.create()
}
  • 注意事项
    • 命名:可命名以提高可读性。
    • 访问:外部需通过类名访问。

7. 包与导入

7.1 包定义:package

  • 语法说明
    • 使用 package 定义命名空间。
  • 应用场景
    • 代码组织、避免命名冲突。
  • 底层原理
    • 编译为 JVM 包结构。
  • 示例代码
1
2
3
4
5
package com.example
fun hello() = println("Hello")
fun main() {
hello() // Hello
}
  • 注意事项
    • 一致性:包名应与目录结构一致。
    • 冲突:避免与其他包名冲突。

7.2 导入:import

  • 语法说明
    • 使用 import 引入类或函数,支持别名(as)。
  • 应用场景
    • 使用外部库、简化代码。
  • 底层原理
    • 编译时解析导入路径。
  • 示例代码
1
2
3
4
import kotlin.math.PI as MathPI
fun main() {
println(MathPI) // 3.141592653589793
}
  • 注意事项
    • 命名冲突:使用 as 解决。
    • 冗余导入:IDE 可优化。

8. 异常处理

8.1 try, catch, finally

  • 语法说明
    • try 定义可能抛异常的代码,catch 处理异常,finally 确保执行。
    • 可作为表达式。
  • 应用场景
    • 错误处理、资源清理。
  • 底层原理
    • 编译为 JVM 的异常表。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
fun main() {
val result = try {
val x = 1 / 0
"Success"
} catch (e: ArithmeticException) {
println("Error: ${e.message}")
"Failed"
} finally {
println("Cleanup")
}
println("Result: $result") // Failed
}
  • 注意事项
    • 异常类型:捕获具体异常,避免用 Exception
    • finally 执行:总是执行,注意资源释放。

8.2 throw

  • 语法说明
    • 使用 throw 抛出异常对象。
  • 应用场景
    • 自定义错误条件。
  • 底层原理
    • 映射到 JVM 的 athrow 指令。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
fun validate(x: Int) {
if (x < 0) throw IllegalArgumentException("Negative not allowed")
}
fun main() {
try {
validate(-1)
} catch (e: IllegalArgumentException) {
println(e.message) // Negative not allowed
}
}
  • 注意事项
    • 异常信息:提供清晰描述。
    • 滥用:不应用作流程控制。

9. 泛型

9.1 泛型类:<T>

  • 语法说明
    • 使用 <T> 定义类型参数。
  • 应用场景
    • 类型安全的容器。
  • 底层原理
    • 编译为 JVM 的泛型擦除,使用 Object 并插入类型检查。
  • 示例代码
1
2
3
4
5
6
class Box<T>(val value: T)
fun main() {
val intBox = Box(42)
val strBox = Box("Kotlin")
println("${intBox.value}, ${strBox.value}")
}
  • 注意事项
    • 类型约束:可用 where 限制。
    • 运行时:无法直接获取 T 类型。

9.2 泛型函数

  • 语法说明
    • 在函数名前加 <T>
  • 应用场景
    • 通用算法。
  • 底层原理
    • 同泛型类,类型擦除。
  • 示例代码
1
2
3
4
5
fun <T> printItem(item: T) = println(item)
fun main() {
printItem(42) // 42
printItem("Kotlin") // Kotlin
}
  • 注意事项
    • 类型推断:复杂场景需显式指定类型。
    • 性能:避免过度泛化。

9.3 协变:out

  • 语法说明
    • 使用 out 限制类型只能作为返回值。
  • 应用场景
    • 生产者模式。
  • 底层原理
    • 编译器确保类型安全。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
interface Producer<out T> {
fun produce(): T
}
class StringProducer : Producer<String> {
override fun produce() = "Hello"
}
fun main() {
val producer: Producer<Any> = StringProducer()
println(producer.produce())
}
  • 注意事项
    • 限制:不能用作输入参数。
    • 理解:需掌握协变概念。

9.4 逆变:in

  • 语法说明
    • 使用 in 限制类型只能作为参数。
  • 应用场景
    • 消费者模式。
  • 底层原理
    • 编译器检查逆变规则。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
interface Consumer<in T> {
fun consume(item: T)
}
class AnyConsumer : Consumer<Any> {
override fun consume(item: Any) = println(item)
}
fun main() {
val consumer: Consumer<String> = AnyConsumer()
consumer.consume("Hello")
}
  • 注意事项
    • 限制:不能用作返回值。
    • 复杂性:与协变配合需小心。

9.5 通配符:*

  • 语法说明
    • 表示未知类型,类似 Java 的 ?
  • 应用场景
    • 类型无关操作。
  • 底层原理
    • 编译为泛型上限 Any?
  • 示例代码
1
2
3
4
fun printList(list: List<*>) = println(list)
fun main() {
printList(listOf(1, "A")) // [1, A]
}
  • 注意事项
    • 限制:无法访问具体类型方法。
    • 替代:可用具体类型替换。

10. 空安全

10.1 可空类型:?

  • 语法说明
    • 在类型后加 ? 表示可为 null
  • 应用场景
    • 处理潜在的 null 值。
  • 底层原理
    • 编译器强制类型检查。
  • 示例代码
1
2
3
4
fun main() {
val str: String? = null
println(str) // null
}
  • 注意事项
    • 过度使用:过多 ? 增加空检查负担。
    • 初始化:尽量推迟到确定非空。

10.2 安全调用:?.

  • 语法说明
    • 若对象为 null,返回 null,否则调用方法。
  • 应用场景
    • 避免空指针异常。
  • 底层原理
    • 编译为条件跳转。
  • 示例代码
1
2
3
4
fun main() {
val str: String? = null
println(str?.length) // null
}
  • 注意事项
    • 链式调用:多级 ?. 返回类型可能是嵌套可空。
    • 性能:频繁使用增加分支。

10.3 Elvis 操作符:?:

  • 语法说明
    • 若左边为 null,返回右边值。
  • 应用场景
    • 提供默认值。
  • 底层原理
    • 编译为条件表达式。
  • 示例代码
1
2
3
4
5
fun main() {
val str: String? = null
val length = str?.length ?: -1
println(length) // -1
}
  • 注意事项
    • 类型一致:左右类型需匹配。
    • 副作用:右边避免复杂逻辑。

10.4 非空断言:!!

  • 语法说明
    • 强制解包,若为 null 抛异常。
  • 应用场景
    • 确信非空时使用。
  • 底层原理
    • 编译为直接访问,若 nullNullPointerException
  • 示例代码
1
2
3
4
fun main() {
val str: String? = "Kotlin"
println(str!!.length) // 6
}
  • 注意事项
    • 风险:滥用导致运行时异常。
    • 替代:优先用 ?.?:

11. 注解

11.1 内置注解

Kotlin 提供了一系列内置注解,主要用于控制编译器行为、与 JVM 平台交互或增强代码语义。以下是所有内置注解的完整列表,涵盖标准库中定义的注解(基于 Kotlin 1.9 及之前版本):


@Deprecated
  • 语法说明
    • 标记代码元素(类、函数、属性等)为废弃状态。
    • 参数:message: String(必填,废弃原因),replaceWith: ReplaceWith(可选,替代方案),level: DeprecationLevel(可选,废弃级别:WARNINGERROR,默认 WARNING)。
  • 应用场景
    • API 维护:提示用户停止使用旧 API。
    • 代码迁移:引导开发者转向新实现。
  • 底层原理
    • 编译器在编译时发出警告或错误(取决于 level),并在生成的 JVM 字节码中添加 @java.lang.Deprecated
  • 示例代码
1
2
3
4
5
6
7
@Deprecated("Use newFunc instead", ReplaceWith("newFunc()"), DeprecationLevel.WARNING)
fun oldFunc() = println("Old")
fun newFunc() = println("New")
fun main() {
oldFunc() // 编译器警告:'oldFunc' is deprecated
newFunc() // New
}
  • 注意事项
    • 信息message 应清晰说明废弃原因。
    • 替代方案ReplaceWith 提供可直接替换的代码,提升迁移效率。
    • 级别:使用 ERROR 时调用处会编译失败,谨慎使用。

@Suppress
  • 语法说明
    • 抑制特定的编译器警告或错误。
    • 参数:可变字符串数组(如 "DEPRECATION"),指定要抑制的警告类型。
  • 应用场景
    • 临时忽略无关警告(如使用废弃 API)。
    • 清理代码时避免过多告警干扰。
  • 底层原理
    • 编译器在分析代码时跳过指定警告的检查,不影响生成的字节码。
  • 示例代码
1
2
3
4
5
6
7
@Deprecated("Use newFunc instead")
fun oldFunc() = println("Old")
fun newFunc() = println("New")
@Suppress("DEPRECATION")
fun main() {
oldFunc() // 无警告
}
  • 注意事项
    • 范围:尽量具体到最小作用域,避免隐藏重要问题。
    • 警告类型:需查阅文档确认有效的警告名称(如 "UNUSED_VARIABLE")。

@JvmOverloads
  • 语法说明
    • 为带有默认参数的函数或构造函数生成 JVM 重载方法。
    • 无参数,直接标注在函数或构造函数上。
  • 应用场景
    • 与 Java 互操作:使 Kotlin 默认参数对 Java 调用者可见。
    • 简化 API:提供多种调用方式。
  • 底层原理
    • 编译器为每个默认参数生成重载方法,JVM 字节码中表现为独立方法。
  • 示例代码
1
2
3
4
5
6
7
@JvmOverloads
fun greet(name: String = "Guest", greeting: String = "Hello") = "$greeting, $name!"
fun main() {
println(greet()) // Hello, Guest!
println(greet("Alice")) // Hello, Alice!
println(greet("Bob", "Hi")) // Hi, Bob!
}
  • 注意事项
    • 参数顺序:默认参数需连续靠后,否则生成不完整。
    • 性能:参数过多时增加字节码大小。
    • 平台限制:仅对 JVM 有效。

@JvmStatic
  • 语法说明
    • 将伴生对象中的函数或属性标记为静态,生成 JVM 静态方法或字段。
    • 应用于伴生对象成员。
  • 应用场景
    • 与 Java 互操作:使伴生对象成员可通过类名直接调用。
    • 工具类设计:模拟 Java 静态方法。
  • 底层原理
    • 编译器在类中生成静态方法,绕过伴生对象实例,直接映射到 JVM 静态调用。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
class Utils {
companion object {
@JvmStatic
fun sayHello() = println("Hello from static")
}
}
fun main() {
Utils.sayHello() // Kotlin 调用
// Java: Utils.sayHello();
}
  • 注意事项
    • 适用范围:仅限伴生对象。
    • 冗余:非 Java 交互时无需使用。

@JvmField
  • 语法说明
    • 将属性暴露为 JVM 的公共字段,跳过 getter/setter。
    • 应用于属性声明。
  • 应用场景
    • 与 Java 互操作:直接访问字段而非通过方法。
    • 性能优化:避免访问器开销。
  • 底层原理
    • 编译器生成 public 字段而非封装属性,移除 Kotlin 的属性封装。
  • 示例代码
1
2
3
4
5
6
7
8
9
class Data {
@JvmField
val id = 42
}
fun main() {
val d = Data()
println(d.id) // 42
// Java: int value = new Data().id;
}
  • 注意事项
    • 封装性:丧失 getter/setter 控制。
    • 限制:不能与 private 或自定义访问器共用。

@Throws
  • 语法说明
    • 指定函数可能抛出的异常,生成 JVM 的 throws 声明。
    • 参数:异常类的 KClass 列表(如 @Throws(IOException::class))。
  • 应用场景
    • 与 Java 互操作:告知 Java 调用者异常类型。
    • 文档化:明确异常行为。
  • 底层原理
    • 编译器在字节码中添加 throws 子句,与 Java 的异常声明一致。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
import java.io.IOException
@Throws(IOException::class)
fun riskyOperation() {
throw IOException("Something went wrong")
}
fun main() {
try {
riskyOperation()
} catch (e: IOException) {
println(e.message) // Something went wrong
}
}
  • 注意事项
    • 必要性:Kotlin 不强制异常声明,仅为 Java 兼容。
    • 类型:需使用 ::class 指定。

@JvmName
  • 语法说明
    • 指定函数或属性在 JVM 中的名称,避免命名冲突。
    • 参数:字符串,表示 JVM 名称。
  • 应用场景
    • 解决签名冲突:如与 Java 方法名冲突。
    • 美化 API:自定义 Java 可见名称。
  • 底层原理
    • 编译器修改生成的 JVM 方法或字段名称。
  • 示例代码
1
2
3
4
5
6
@JvmName("customGreet")
fun greet() = println("Hello")
fun main() {
greet() // Hello
// Java: MyClass.customGreet();
}
  • 注意事项
    • 唯一性:新名称需避免冲突。
    • 范围:仅影响 JVM 签名。

@JvmMultifileClass
  • 语法说明
    • 将多个文件中的顶层函数合并为单个 JVM 类。
    • @file:JvmName 配合使用。
  • 应用场景
    • 模块化开发:将分散的顶层函数整合为一个类。
    • Java 互操作:统一访问入口。
  • 底层原理
    • 编译器将多个文件中的函数合并到一个类文件中。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// File1.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
fun util1() = println("Util 1")

// File2.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
fun util2() = println("Util 2")

fun main() {
util1() // Util 1
util2() // Util 2
// Java: Utils.util1(); Utils.util2();
}
  • 注意事项
    • 配合使用:必须与 @file:JvmName 一起使用。
    • 一致性:所有文件需相同 JvmName

@Synchronized
  • 语法说明
    • 标记函数为同步,类似 Java 的 synchronized 方法。
    • 应用于函数。
  • 应用场景
    • 多线程编程:确保线程安全。
  • 底层原理
    • 编译器生成 JVM 的 synchronized 块,锁定函数所属对象。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
class Counter {
var count = 0
@Synchronized
fun increment() {
count++
}
}
fun main() {
val counter = Counter()
counter.increment()
println(counter.count) // 1
}
  • 注意事项
    • 性能:同步降低并发性,谨慎使用。
    • 范围:仅锁定当前实例。

@Volatile
  • 语法说明
    • 标记属性为 volatile,确保线程间可见性。
    • 应用于属性。
  • 应用场景
    • 多线程编程:避免线程缓存问题。
  • 底层原理
    • 映射到 JVM 的 volatile 修饰符,保证内存一致性。
  • 示例代码
1
2
3
4
5
6
7
8
9
class ThreadSafe {
@Volatile
var flag = false
}
fun main() {
val ts = ThreadSafe()
ts.flag = true
println(ts.flag) // true
}
  • 注意事项
    • 限制:仅适用于 var,不可用于局部变量。
    • 开销:增加内存屏障,影响性能。

@Strictfp
  • 语法说明
    • 标记函数或类使用严格浮点运算,遵循 IEEE 754 标准。
    • 应用于函数或类。
  • 应用场景
    • 高精度浮点计算:确保跨平台一致性。
  • 底层原理
    • 编译器生成 JVM 的 strictfp 修饰符,禁用浮点优化。
  • 示例代码
1
2
3
4
5
@Strictfp
fun compute(x: Double): Double = x * 2.0
fun main() {
println(compute(3.14)) // 6.28
}
  • 注意事项
    • 使用场景:极少使用,除非明确要求一致性。
    • 兼容性:仅 JVM 有效。

@PublishedApi
  • 语法说明
    • 标记 internal 函数或属性为公开 API,可被内联函数间接访问。
  • 应用场景
    • 库开发:在模块内隐藏实现细节,同时允许内联函数使用。
  • 底层原理
    • 编译器将 internal 元素提升为 public,但仍限制模块外直接访问。
  • 示例代码
1
2
3
4
5
6
@PublishedApi
internal fun internalFunc() = "Internal"
inline fun publicFunc() = internalFunc()
fun main() {
println(publicFunc()) // Internal
}
  • 注意事项
    • 限制:仅与 inline 配合。
    • 封装性:谨慎使用,避免泄露实现。

@SinceKotlin
  • 语法说明
    • 标记代码元素自某个 Kotlin 版本起可用。
    • 参数:版本号字符串(如 "1.3")。
  • 应用场景
    • API 文档化:提示最低支持版本。
  • 底层原理
    • 仅用于元数据记录,不影响编译或运行。
  • 示例代码
1
2
3
4
5
@SinceKotlin("1.3")
fun modernFeature() = println("Available since 1.3")
fun main() {
modernFeature() // Available since 1.3
}
  • 注意事项
    • 版本检查:仅提示,不强制执行。
    • 文档:建议与版本控制结合。

@OptIn
  • 语法说明
    • 声明使用实验性或不稳定的 API。
    • 参数:注解类的 KClass(如 @OptIn(ExperimentalTime::class))。
  • 应用场景
    • 使用实验性特性:如协程、时间 API。
  • 底层原理
    • 编译器检查是否标记,未标记时发出警告或错误。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
@OptIn(ExperimentalTime::class)
fun measure() {
val duration = measureTime { Thread.sleep(100) }
println(duration) // ~100ms
}
fun main() {
measure()
}
  • 注意事项
    • 风险:实验性 API 可能变更。
    • 范围:可用于文件或模块级别。

@file:JvmName
  • 语法说明
    • 指定文件编译后在 JVM 中的类名。
    • 参数:字符串,表示类名。
  • 应用场景
    • 顶层函数命名:避免默认的 FileKt 类名。
    • @JvmMultifileClass 配合。
  • 底层原理
    • 编译器修改生成类的名称。
  • 示例代码
1
2
3
4
5
6
@file:JvmName("MyUtils")
fun util() = println("Utility")
fun main() {
util() // Utility
// Java: MyUtils.util();
}
  • 注意事项
    • 冲突:确保名称唯一。
    • 范围:仅文件级有效。

@file:Suppress
  • 语法说明
    • 在文件级别抑制警告。
    • 参数:警告类型字符串数组。
  • 应用场景
    • 文件级警告清理。
  • 底层原理
    • @Suppress,作用于整个文件。
  • 示例代码
1
2
3
4
5
@file:Suppress("UNUSED_VARIABLE")
fun main() {
val unused = 42 // 无警告
println("Done")
}
  • 注意事项
    • 范围:影响整个文件,谨慎使用。
    • 替代:局部 @Suppress 更精准。

完整示例整合

以下是一个综合示例,展示部分内置注解的协同使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@file:JvmName("Demo")
@Deprecated("Use newApi instead", ReplaceWith("newApi()"))
fun oldApi() = println("Old API")

@JvmOverloads
fun newApi(message: String = "New", count: Int = 1) = println("$message repeated $count times")

class Example {
companion object {
@JvmStatic
fun staticMethod() = println("Static")
}

@Volatile
var flag = false

@Synchronized
fun syncMethod() {
flag = true
}
}

@OptIn(ExperimentalTime::class)
fun measureTime() {
val duration = kotlin.time.measureTime { Thread.sleep(100) }
println("Took $duration")
}

@Suppress("DEPRECATION")
fun main() {
oldApi() // Old API (警告被抑制)
newApi() // New repeated 1 times
newApi("Hi") // Hi repeated 1 times
Example.staticMethod() // Static
measureTime() // Took ~100ms
}

11.2 自定义注解:annotation

  • 语法说明
    • 使用 annotation class 定义。
  • 应用场景
    • 元编程、框架开发。
  • 底层原理
    • 编译为 JVM 注解。
  • 示例代码
1
2
3
4
5
6
annotation class MyAnnotation(val priority: Int)
@MyAnnotation(1)
fun annotated() = println("Annotated")
fun main() {
annotated()
}
  • 注意事项
    • 运行时:需加 @Retention 指定保留级别。
    • 参数:仅支持基本类型和枚举。

二、现代 Kotlin 新特性

1. Kotlin 1.0+

1.1 Lambda 表达式:{ x -> x * 2 }

  • 语法说明
    • 格式:{ params -> expression },简化为 { it }(单参数)。
  • 应用场景
    • 集合操作、事件处理。
  • 底层原理
    • 编译为匿名类或内联代码(若加 inline)。
  • 示例代码
1
2
3
4
5
fun main() {
val list = listOf(1, 2, 3)
val doubled = list.map { x -> x * 2 }
println(doubled) // [2, 4, 6]
}
  • 注意事项
    • 性能:未内联时生成对象。
    • 可读性:复杂逻辑不适合。

1.2 扩展函数

  • 语法说明
    • 在类外定义方法,格式:fun ReceiverType.name() { ... }
  • 应用场景
    • 扩展标准库、工具函数。
  • 底层原理
    • 编译为静态方法,接收者作为参数。
  • 示例代码
1
2
3
4
fun String.addExclamation() = "$this!"
fun main() {
println("Hello".addExclamation()) // Hello!
}
  • 注意事项
    • 冲突:与类方法冲突时优先类内方法。
    • 访问:不能访问私有成员。

1.3 中缀函数:infix

  • 语法说明
    • 使用 infix 修饰,允许中缀调用。
  • 应用场景
    • 提高代码可读性。
  • 底层原理
    • 编译为普通方法调用。
  • 示例代码
1
2
3
4
infix fun Int.plus(x: Int) = this + x
fun main() {
println(5 plus 3) // 8
}
  • 注意事项
    • 限制:需单一参数。
    • 滥用:影响代码一致性。

1.4 运算符重载:operator

  • 语法说明
    • 使用 operator 定义运算符行为。
  • 应用场景
    • 自定义数学对象。
  • 底层原理
    • 编译为方法调用。
  • 示例代码
1
2
3
4
5
6
7
8
data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point) = Point(x + other.x, y + other.y)
}
fun main() {
val p1 = Point(1, 2)
val p2 = Point(3, 4)
println(p1 + p2) // Point(x=4, y=6)
}
  • 注意事项
    • 语义:保持运算符直观含义。
    • 一致性:与标准库一致。

2. Kotlin 1.1

2.1 协程:suspend, launch

  • 语法说明
    • suspend:标记挂起函数。
    • launch:启动协程。
  • 应用场景
    • 异步编程、网络请求。
  • 底层原理
    • 基于状态机和续体(continuation),编译器生成回调逻辑。
  • 示例代码
1
2
3
4
5
6
7
8
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(1000L)
println("World")
}
println("Hello")
}
  • 注意事项
    • 依赖:需引入 kotlinx-coroutines
    • 作用域:需在协程作用域内调用。

3. Kotlin 1.3

3.1 内联类:inline class

  • 语法说明
    • 使用 inline class 定义单值包装类。
  • 应用场景
    • 类型安全、性能优化。
  • 底层原理
    • 编译时展开为原始类型。
  • 示例代码
1
2
3
4
5
inline class Name(val value: String)
fun main() {
val name = Name("Kotlin")
println(name.value) // Kotlin
}
  • 注意事项
    • 限制:仅限单一属性。
    • 兼容性:早期版本不支持。

3.2 无符号整数:UInt, ULong

  • 语法说明
    • UInt:32 位无符号整数,ULong:64 位,加 uU 后缀。
  • 应用场景
    • 正整数计算。
  • 底层原理
    • 编译为有符号整数,运行时模拟无符号行为。
  • 示例代码
1
2
3
4
5
fun main() {
val uint: UInt = 42u
val ulong: ULong = 123UL
println("$uint, $ulong")
}
  • 注意事项
    • 运算:需注意类型匹配。
    • 范围:超出需转换。

4. Kotlin 1.4

4.1 SAM 转换改进

  • 语法说明
    • 单方法接口支持 Lambda 转换。
  • 应用场景
    • 简化 Java 接口调用。
  • 底层原理
    • 编译为接口实现。
  • 示例代码
1
2
3
4
5
6
7
fun interface Action {
fun run()
}
fun main() {
val action = Action { println("Run") }
action.run()
}
  • 注意事项
    • 单一方法:仅限单抽象方法。
    • 明确性:避免歧义。

4.2 尾随逗号

  • 语法说明
    • 参数列表、集合末尾允许逗号。
  • 应用场景
    • 代码格式化。
  • 底层原理
    • 语法糖,无运行时影响。
  • 示例代码
1
2
3
4
val list = listOf(
1,
2,
)
  • 注意事项
    • 兼容性:旧版本不支持。
    • 一致性:团队需统一风格。

5. Kotlin 1.5

5.1 密封接口:sealed interface

  • 语法说明
    • 使用 sealed interface 限制实现类。
  • 应用场景
    • 模式匹配。
  • 底层原理
    • 编译器检查实现。
  • 示例代码
1
2
3
4
5
6
sealed interface Expr
data class Num(val value: Int) : Expr
fun main() {
val expr: Expr = Num(42)
println((expr as Num).value)
}
  • 注意事项
    • 范围:实现类需在同一模块。
    • 版本:需 1.5+。

5.2 内联值类:value class

  • 语法说明
    • 使用 value class 定义单值类。
  • 应用场景
    • 类型安全。
  • 底层原理
    • 编译时展开。
  • 示例代码
1
2
3
4
5
value class Password(val value: String)
fun main() {
val pwd = Password("secret")
println(pwd.value)
}
  • 注意事项
    • 限制:单一属性。
    • 兼容性:需 1.5+。

6. Kotlin 1.6

6.1 挂起函数类型:suspend () -> Unit

  • 语法说明
    • 定义挂起函数类型。
  • 应用场景
    • 协程回调。
  • 底层原理
    • 编译为续体类型。
  • 示例代码
1
2
3
4
fun main() {
val suspendFunc: suspend () -> Unit = { println("Suspended") }
// 需要协程作用域调用
}
  • 注意事项
    • 调用:需协程作用域。
    • 版本:需 1.6+。

7. Kotlin 1.8

7.1 上下文接收者:context

  • 语法说明
    • 使用 context(Type) 指定接收者。
  • 应用场景
    • DSL 设计。
  • 底层原理
    • 编译为隐式参数。
  • 示例代码
1
2
3
4
5
context(String)
fun printWithContext() = println(this)
fun main() {
with("Hello") { printWithContext() } // Hello
}
  • 注意事项
    • 实验性:需启用特性。
    • 复杂度:增加理解难度。

8. Kotlin 1.9+

8.1 多平台改进

  • 语法说明
    • 使用 expectactual 定义跨平台代码。
  • 应用场景
    • 多平台开发。
  • 底层原理
    • 编译器生成平台特定代码。
  • 示例代码
1
2
3
4
5
6
7
8
9
expect class Platform {
fun name(): String
}
actual class Platform actual constructor() {
actual fun name() = "JVM"
}
fun main() {
println(Platform().name())
}
  • 注意事项
    • 配置:需多平台项目设置。
    • 一致性:实现需匹配。

8.2 K2 编译器特性

  • 语法说明
    • K2 是新编译器,提升性能。
  • 应用场景
    • 更快编译、更严格检查。
  • 底层原理
    • 重写编译流程。
  • 示例代码
    • 无特定语法,仅编译器特性。
  • 注意事项
    • 稳定性:仍在完善。
    • 启用:需配置。

三、其他特性

1. 标准库扩展

1.1 集合:List, Set, Map

  • 语法说明
    • listOf():不可变列表。
    • setOf():不可变集合。
    • mapOf():不可变映射。
    • 可变版本:mutableListOf(), mutableSetOf(), mutableMapOf()
  • 应用场景
    • 数据存储、查询。
  • 底层原理
    • 基于 Java 集合类(如 ArrayList, HashSet, HashMap)。
  • 示例代码
1
2
3
4
5
6
7
8
fun main() {
val list = listOf(1, 2, 3)
val set = setOf(1, 2, 2) // [1, 2]
val map = mapOf("a" to 1, "b" to 2)
val mutableList = mutableListOf(1, 2)
mutableList.add(3)
println("$list, $set, $map, $mutableList")
}
  • 注意事项
    • 不可变性listOf() 不支持修改。
    • 性能:选择合适集合类型。

1.2 字符串:String, StringBuilder

  • 语法说明
    • String:不可变字符串。
    • StringBuilder:可变字符串缓冲区。
  • 应用场景
    • 文本处理、动态拼接。
  • 底层原理
    • String 映射到 java.lang.String
    • StringBuilder 使用 java.lang.StringBuilder
  • 示例代码
1
2
3
4
5
fun main() {
val str = "Hello"
val sb = StringBuilder().append("Hello").append(" World")
println("$str, ${sb.toString()}")
}
  • 注意事项
    • 性能:大量拼接用 StringBuilder
    • 不可变性String 修改生成新对象。

1.3 IO:java.io

  • 语法说明
    • 使用 Java 的 IO 类(如 File)。
  • 应用场景
    • 文件读写。
  • 底层原理
    • 直接调用 Java IO 库。
  • 示例代码
1
2
3
4
5
import java.io.File
fun main() {
File("test.txt").writeText("Hello")
println(File("test.txt").readText()) // Hello
}
  • 注意事项
    • 异常:需处理 IO 异常。
    • 资源:确保关闭流。

1.4 并发:kotlin.coroutines

  • 语法说明
    • 使用 kotlinx.coroutines 提供协程支持。
  • 应用场景
    • 异步任务、并发处理。
  • 底层原理
    • 基于状态机和续体。
  • 示例代码
1
2
3
4
5
6
7
8
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(1000L)
println("World")
}
println("Hello")
}
  • 注意事项
    • 依赖:需添加库。
    • 取消:注意协程生命周期。

2. 反射与运行时

2.1 类引用:::class

  • 语法说明
    • 获取类的 KClass 对象。
  • 应用场景
    • 反射、元编程。
  • 底层原理
    • 返回运行时类引用。
  • 示例代码
1
2
3
4
fun main() {
val ref = String::class
println(ref.simpleName) // String
}
  • 注意事项
    • 性能:反射开销大。
    • 类型:区分 ::class::class.java

2.2 函数引用:::function

  • 语法说明
    • 获取函数引用。
  • 应用场景
    • 函数式编程。
  • 底层原理
    • 编译为函数对象。
  • 示例代码
1
2
3
4
5
fun hello() = println("Hello")
fun main() {
val ref = ::hello
ref() // Hello
}
  • 注意事项
    • 适用性:仅限顶层或成员函数。
    • 性能:避免频繁创建。

2.3 反射库:kotlin.reflect

  • 语法说明
    • 使用 kotlin.reflect 访问类、属性等。
  • 应用场景
    • 动态检查。
  • 底层原理
    • 基于 JVM 反射。
  • 示例代码
1
2
3
4
5
6
import kotlin.reflect.full.memberProperties
data class Person(val name: String)
fun main() {
val props = Person::class.memberProperties
println(props.map { it.name }) // [name]
}
  • 注意事项
    • 依赖:需添加 kotlin-reflect
    • 开销:避免在性能敏感处使用。

3. 委托

3.1 属性委托:by lazy, by Delegates

  • 语法说明
    • 使用 by 将属性委托给代理对象。
    • lazy:延迟初始化,线程安全。
    • Delegates.observable:属性变化监听。
  • 应用场景
    • lazy:延迟加载资源。
    • observable:状态监听(如 UI 更新)。
  • 底层原理
    • lazy:编译为 Lazy 对象,首次访问时初始化。
    • observable:使用 ObservableProperty 包装,调用回调。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import kotlin.properties.Delegates
fun main() {
// lazy
val lazyVal: String by lazy {
println("Computed")
"Lazy"
}
println(lazyVal) // Computed, Lazy
println(lazyVal) // Lazy(不再计算)

// observable
var obsVal: String by Delegates.observable("Init") { property, old, new ->
println("${property.name}: $old -> $new")
}
obsVal = "New" // obsVal: Init -> New
obsVal = "Final" // obsVal: New -> Final
}
  • 注意事项
    • lazy 线程安全:默认同步,需明确模式(如 LazyThreadSafetyMode.NONE)。
    • observable 开销:每次赋值触发回调,注意性能。
    • 初始化lazy 不可重新赋值。

3.2 类委托:by

  • 语法说明
    • 使用 by 将接口实现委托给对象。
  • 应用场景
    • 组合优于继承、代理模式。
  • 底层原理
    • 编译为代理调用。
  • 示例代码
1
2
3
4
5
6
7
8
9
10
11
interface Printer {
fun print()
}
class PrinterImpl : Printer {
override fun print() = println("Printing")
}
class Delegator(printer: Printer) : Printer by printer
fun main() {
val delegator = Delegator(PrinterImpl())
delegator.print() // Printing
}
  • 注意事项
    • 覆盖:委托后仍可重写方法。
    • 依赖:确保委托对象可靠。