语法树 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 位有符号整数,范围 -128
到 127
,显式声明为 Byte
。
Short
:16 位有符号整数,范围 -32768
到 32767
,显式声明为 Short
。
Int
:32 位有符号整数,范围 -2,147,483,648
到 2,147,483,647
,默认整数类型。
Long
:64 位有符号整数,范围 -9,223,372,036,854,775,808
到 9,223,372,036,854,775,807
,需加 L
后缀。
支持类型推断,如 val x = 42
推断为 Int
。
应用场景 :
Byte
:节省内存,适用于小型数据(如网络协议中的标志位、图像像素值)。
Short
:较少使用,适用于特定硬件接口或与旧系统交互。
Int
:日常计数、数组索引、循环变量。
Long
:大范围数据,如时间戳(毫秒)、文件大小、数据库 ID。
底层原理 :
在 JVM 上,分别映射为 Java 的 byte
、short
、int
、long
,为原始类型以优化性能。
当声明为可空类型(如 Int?
)或用于泛型时,装箱为 java.lang.Byte
、Short
、Integer
、Long
。
编译器优化字面量,例如 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 " ) val overflow: Byte = (byte + 1 ).toByte() println("Overflow Byte: $overflow " ) val nullableLong: Long ? = null println("Nullable Long: $nullableLong " ) }
注意事项 :
溢出风险 :Byte
和 Short
操作超出范围不会自动提升类型,需手动转换(如 (byte + 1).toByte()
),否则溢出(如 127 + 1 = -128)。
类型转换 :必须显式转换(如 toInt()
),否则编译错误,避免隐式转换导致的意外。
性能 :优先使用 Int
,因为它是 JVM 的默认整数类型,Byte
和 Short
在某些场景可能因装箱而降低性能。
L
后缀 :Long
字面量忘记加 L
会默认推断为 Int
,可能导致溢出。
1.2 浮点型:Float
, Double
语法说明 :
Float
:32 位单精度浮点数,约 6-7 位有效数字,需加 f
或 F
后缀(如 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
映射为 float
,Double
映射为 double
,可空时装箱为 java.lang.Float
和 Double
。
运算结果可能因舍入而有微小误差。
示例代码 :
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 println("Scientific Float: $sciFloat " ) val sumFloat = 0.1f + 0.2f println("Float 0.1 + 0.2 = $sumFloat " ) val sumDouble = 0.1 + 0.2 println("Double 0.1 + 0.2 = $sumDouble " ) 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' println("Char: $char , Unicode: $unicodeChar , Code: ${char.code} " ) val newline: Char = '\n' print("Line1${newline} Line2" ) val nextChar = char + 1 println("Next Char: $nextChar " ) val nullableChar: Char ? = null println("Nullable Char: $nullableChar " ) }
注意事项 :
与数字区分 :Char
不能直接当作整数使用,需用 .code
转换。
单引号 :使用双引号(如 "A"
)会推断为 String
,导致类型错误。
范围限制 :超出 Unicode 范围(如 \uFFFF
以上)无效。
运算结果 :Char
加减返回 Int
,需转换回 Char
。
1.4 布尔型:Boolean
语法说明 :
表示 true
或 false
,用于逻辑判断。
可声明为可空类型(如 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 " ) val status = when (isDone) { true -> "Completed" false -> "Pending" null -> "Unknown" } println("Status: $status " ) }
注意事项 :
可空处理 :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 " ) count = 20 println("Updated: $count " ) var name: String = "Kotlin" name = "Java" println("Name: $name " ) run { var local = 5 local += 1 println("Local: $local " ) } }
注意事项 :
过度使用 :滥用 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 println("Pi: $pi " ) val list = mutableListOf(1 , 2 ) list.add(3 ) println("List: $list " ) val x = 5 val max = if (x > 0 ) x else 0 println("Max: $max " ) }
注意事项 :
引用 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} " ) println("a - b = ${a - b} " ) println("a * b = ${a * b} " ) println("a / b = ${a / b} " ) println("a % b = ${a % b} " ) println("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} " ) println("x < y: ${x < y} " ) val str1 = "Kotlin" val str2 = "Kotlin" println("str1 === str2: ${str1 === str2} " ) }
注意事项 :
浮点比较 :避免直接用 ==
,因精度误差可能导致错误。
===
使用 :仅适用于对象引用,基本类型始终用 ==
。
自定义类 :==
需要重写 equals()
。
3.3 逻辑运算符:&&
, ||
, !
语法说明 :
&&
:逻辑与,短路求值。
||
:逻辑或,短路求值。
!
:逻辑非。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 6 7 fun main () { val a = true val b = false println("a && b: ${a && b} " ) println("a || b: ${a || b} " ) println("!a: ${!a} " ) }
注意事项 :
副作用 :短路求值可能跳过右边代码,注意逻辑顺序。
可空类型 :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 val y = 3 println("x and y: ${x and y} " ) println("x or y: ${x or y} " ) println("x xor y: ${x xor y} " ) println("x shl 1: ${x shl 1 } " ) println("x shr 1: ${x shr 1 } " ) }
注意事项 :
符号位 :shr
是带符号右移,负数需注意。
溢出 :移位不检查范围,可能导致意外结果。
3.5 赋值运算符:=
, +=
, -=
, *=
, /=
语法说明 :
=
:简单赋值。
+=
, -=
, *=
, /=
:组合赋值。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 6 7 fun main () { var x = 10 x += 5 println("x += 5: $x " ) x *= 2 println("x *= 2: $x " ) }
注意事项 :
不可变变量 :val
不支持赋值运算符。
类型匹配 :右边类型需与左边兼容。
3.6 其他运算符:?:
, ?.
, !!
, in
语法说明 :
?:
(Elvis):若左边为 null
,返回右边值。
?.
:安全调用,若对象为 null
返回 null
。
!!
:非空断言,若为 null
抛异常。
in
:检查是否在范围或集合中。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 6 7 fun main () { val str: String? = null println("Safe call: ${str?.length} " ) println("Elvis: ${str?.length ?: 0 } " ) println("In range: ${3 in 1. .5 } " ) }
注意事项 :
!!
风险 :滥用可能抛 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 " ) }
注意事项 :
完整性 :作为表达式时必须有 else
,否则编译错误。
嵌套 :过多嵌套降低可读性,考虑用 when
。
4.2 分支语句:when
语法说明 :
替代 switch
,支持多种条件(如值匹配、范围检查、is
类型检查)。
可作为表达式。
应用场景 :
底层原理 :
示例代码 :
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 " ) }
注意事项 :
覆盖性 :作为表达式时需覆盖所有情况或加 else
。
性能 :复杂条件可能生成较多字节码。
4.3 循环:for
, while
, do-while
语法说明 :
for
:for (item in collection/range) { ... }
,支持范围、步长。
while
:while (condition) { ... }
。
do-while
:do { ... } 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 " ) println() var x = 0 while (x < 3 ) { print("$x " ) x++ } println() do { print("$x " ) x-- } while (x > 0 ) }
注意事项 :
范围对象 :for
需可迭代对象。
无限循环 :while (true)
需确保退出条件。
4.4 跳转:break
, continue
, return
语法说明 :
break
:退出循环。
continue
:跳到下一次迭代。
return
:返回函数结果。
支持标签(如 break@label
)。
应用场景 :
底层原理 :
示例代码 :
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 " ) } } println() for (i in 1. .5 ) { if (i == 3 ) continue print("$i " ) } }
注意事项 :
标签 :多重循环需正确使用标签,避免跳错。
可读性 :过多跳转降低代码清晰度。
5. 函数 5.1 函数定义:fun
语法说明 :
格式:fun name(params): ReturnType { ... }
。
返回类型可选(类型推断)。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 6 fun add (a: Int , b: Int ) : Int { return a + b } fun main () { println(add(3 , 4 )) }
注意事项 :
返回类型 :复杂函数建议显式声明返回类型。
命名 :遵循清晰命名规范。
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 = "#" ) printItems("X" ) }
注意事项 :
顺序 :默认参数应放在 vararg
后。
唯一性 :一个函数只能有一个 vararg
。
5.3 单表达式函数:=
语法说明 :
使用 =
替代 {}
和 return
,适用于简单函数。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 fun multiply (a: Int , b: Int ) = a * bfun main () { println(multiply(2 , 3 )) }
注意事项 :
可读性 :复杂逻辑不适合单表达式。
类型推断 :返回值类型需明确。
5.4 匿名函数
语法说明 :
格式:fun(params) = expression
,无函数名。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 fun main () { val anon = fun (x: Int ) = x * 2 println(anon(5 )) }
注意事项 :
性能 :频繁创建可能增加开销。
使用范围 :适合局部使用。
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 }) }
注意事项 :
性能 :未加 inline
会生成对象,影响效率。
类型复杂性 :参数类型需清晰定义。
6. 类与对象 6.1 类定义:class
语法说明 :
格式:class Name(params) { ... }
,主构造函数在类头。
应用场景 :
底层原理 :
示例代码 :
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() }
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 ) }
注意事项 :
委托 :次构造函数必须调用主构造函数。
复杂度 :过多构造函数降低可读性。
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) }
注意事项 :
自定义访问器 :避免无限递归(如 get() = size
)。
初始化 :必须初始化或延迟。
6.4 访问控制:public
, private
, protected
, internal
语法说明 :
public
:默认,公开。
private
:类内可见。
protected
:类及子类可见。
internal
:模块内可见。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 class Example { private val secret = 42 protected val subclassVisible = "Protected" internal val moduleVisible = "Internal" }
注意事项 :
internal
:模块定义需明确。
过度限制 :影响扩展性。
6.5 继承:open
, :
1 2 open class Animal (val name: String)class Dog (name: String) : Animal(name)
注意事项 :
open
必要性 :类默认不可继承。
单一继承 :Kotlin 不支持多重继承。
6.6 接口:interface
1 2 3 4 5 6 interface Flyable { fun fly () } class Bird : Flyable { override fun fly () = println("Flying" ) }
注意事项 :
实现冲突 :多接口需处理方法冲突。
默认实现 :避免过度依赖。
6.7 抽象类: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()
等。
应用场景 :
底层原理 :
示例代码 :
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" )) }
注意事项 :
主构造函数 :至少一个参数。
继承限制 :不可被 open
。
6.9 对象声明:object
1 2 3 4 5 6 object Singleton { fun hello () = println("Hello" ) } fun main () { Singleton.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
1 2 3 4 5 package com.examplefun hello () = println("Hello" )fun main () { hello() }
注意事项 :
一致性 :包名应与目录结构一致。
冲突 :避免与其他包名冲突。
7.2 导入:import
语法说明 :
使用 import
引入类或函数,支持别名(as
)。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 import kotlin.math.PI as MathPIfun main () { println(MathPI) }
注意事项 :
命名冲突 :使用 as
解决。
冗余导入 :IDE 可优化。
8. 异常处理 8.1 try
, catch
, finally
语法说明 :
try
定义可能抛异常的代码,catch
处理异常,finally
确保执行。
可作为表达式。
应用场景 :
底层原理 :
示例代码 :
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 " ) }
注意事项 :
异常类型 :捕获具体异常,避免用 Exception
。
finally
执行 :总是执行,注意资源释放。
8.2 throw
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) } }
注意事项 :
异常信息 :提供清晰描述。
滥用 :不应用作流程控制。
9. 泛型 9.1 泛型类:<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 泛型函数
1 2 3 4 5 fun <T> printItem (item: T ) = println(item)fun main () { printItem(42 ) printItem("Kotlin" ) }
注意事项 :
类型推断 :复杂场景需显式指定类型。
性能 :避免过度泛化。
9.3 协变: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
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 通配符:*
1 2 3 4 fun printList (list: List <*>) = println(list)fun main () { printList(listOf(1 , "A" )) }
注意事项 :
限制 :无法访问具体类型方法。
替代 :可用具体类型替换。
10. 空安全 10.1 可空类型:?
1 2 3 4 fun main () { val str: String? = null println(str) }
注意事项 :
过度使用 :过多 ?
增加空检查负担。
初始化 :尽量推迟到确定非空。
10.2 安全调用:?.
语法说明 :
若对象为 null
,返回 null
,否则调用方法。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 fun main () { val str: String? = null println(str?.length) }
注意事项 :
链式调用 :多级 ?.
返回类型可能是嵌套可空。
性能 :频繁使用增加分支。
10.3 Elvis 操作符:?:
1 2 3 4 5 fun main () { val str: String? = null val length = str?.length ?: -1 println(length) }
注意事项 :
类型一致 :左右类型需匹配。
副作用 :右边避免复杂逻辑。
10.4 非空断言:!!
语法说明 :
应用场景 :
底层原理 :
编译为直接访问,若 null
抛 NullPointerException
。
示例代码 :
1 2 3 4 fun main () { val str: String? = "Kotlin" println(str!!.length) }
注意事项 :
风险 :滥用导致运行时异常。
替代 :优先用 ?.
或 ?:
。
11. 注解 11.1 内置注解 Kotlin 提供了一系列内置注解,主要用于控制编译器行为、与 JVM 平台交互或增强代码语义。以下是所有内置注解的完整列表,涵盖标准库中定义的注解(基于 Kotlin 1.9 及之前版本):
@Deprecated
语法说明 :
标记代码元素(类、函数、属性等)为废弃状态。
参数:message: String
(必填,废弃原因),replaceWith: ReplaceWith
(可选,替代方案),level: DeprecationLevel
(可选,废弃级别:WARNING
或 ERROR
,默认 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() newFunc() }
注意事项 :
信息 :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()) println(greet("Alice" )) println(greet("Bob" , "Hi" )) }
注意事项 :
参数顺序 :默认参数需连续靠后,否则生成不完整。
性能 :参数过多时增加字节码大小。
平台限制 :仅对 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() }
注意事项 :
适用范围 :仅限伴生对象。
冗余 :非 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) }
注意事项 :
封装性 :丧失 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) } }
注意事项 :
必要性 :Kotlin 不强制异常声明,仅为 Java 兼容。
类型 :需使用 ::class
指定。
@JvmName
语法说明 :
指定函数或属性在 JVM 中的名称,避免命名冲突。
参数:字符串,表示 JVM 名称。
应用场景 :
解决签名冲突:如与 Java 方法名冲突。
美化 API:自定义 Java 可见名称。
底层原理 :
示例代码 :
1 2 3 4 5 6 @JvmName("customGreet" ) fun greet () = println("Hello" )fun main () { greet() }
注意事项 :
唯一性 :新名称需避免冲突。
范围 :仅影响 JVM 签名。
@JvmMultifileClass
语法说明 :
将多个文件中的顶层函数合并为单个 JVM 类。
与 @file:JvmName
配合使用。
应用场景 :
模块化开发:将分散的顶层函数整合为一个类。
Java 互操作:统一访问入口。
底层原理 :
示例代码 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @file:JvmName ("Utils" )@file:JvmMultifileClass fun util1 () = println("Util 1" )@file:JvmName ("Utils" )@file:JvmMultifileClass fun util2 () = println("Util 2" )fun main () { util1() 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) }
注意事项 :
性能 :同步降低并发性,谨慎使用。
范围 :仅锁定当前实例。
@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) }
注意事项 :
限制 :仅适用于 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 )) }
注意事项 :
使用场景 :极少使用,除非明确要求一致性。
兼容性 :仅 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()) }
注意事项 :
限制 :仅与 inline
配合。
封装性 :谨慎使用,避免泄露实现。
@SinceKotlin
语法说明 :
标记代码元素自某个 Kotlin 版本起可用。
参数:版本号字符串(如 "1.3"
)。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 @SinceKotlin("1.3" ) fun modernFeature () = println("Available since 1.3" )fun main () { modernFeature() }
注意事项 :
版本检查 :仅提示,不强制执行。
文档 :建议与版本控制结合。
@OptIn
语法说明 :
声明使用实验性或不稳定的 API。
参数:注解类的 KClass
(如 @OptIn(ExperimentalTime::class)
)。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 6 7 8 9 10 import kotlin.time.ExperimentalTimeimport kotlin.time.measureTime@OptIn(ExperimentalTime::class) fun measure () { val duration = measureTime { Thread.sleep(100 ) } println(duration) } 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() }
@file: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() newApi() newApi("Hi" ) Example.staticMethod() measureTime() }
11.2 自定义注解:annotation
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 }
(单参数)。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 fun main () { val list = listOf(1 , 2 , 3 ) val doubled = list.map { x -> x * 2 } println(doubled) }
注意事项 :
性能 :未内联时生成对象。
可读性 :复杂逻辑不适合。
1.2 扩展函数
语法说明 :
在类外定义方法,格式:fun ReceiverType.name() { ... }
。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 fun String.addExclamation () = "$this !" fun main () { println("Hello" .addExclamation()) }
注意事项 :
冲突 :与类方法冲突时优先类内方法。
访问 :不能访问私有成员。
1.3 中缀函数:infix
1 2 3 4 infix fun Int .plus (x: Int ) = this + xfun main () { println(5 plus 3 ) }
1.4 运算符重载: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) }
注意事项 :
语义 :保持运算符直观含义。
一致性 :与标准库一致。
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
1 2 3 4 5 inline class Name (val value: String)fun main () { val name = Name("Kotlin" ) println(name.value) }
3.2 无符号整数:UInt
, ULong
语法说明 :
UInt
:32 位无符号整数,ULong
:64 位,加 u
或 U
后缀。
应用场景 :
底层原理 :
示例代码 :
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 转换改进
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 ) : Exprfun main () { val expr: Expr = Num(42 ) println((expr as Num).value) }
5.2 内联值类:value class
1 2 3 4 5 value class Password (val value: String) fun main () { val pwd = Password("secret" ) println(pwd.value) }
6. Kotlin 1.6 6.1 挂起函数类型:suspend () -> Unit
1 2 3 4 fun main () { val suspendFunc: suspend () -> Unit = { println("Suspended" ) } }
7. Kotlin 1.8 7.1 上下文接收者:context
1 2 3 4 5 context(String) fun printWithContext () = println(this )fun main () { with("Hello" ) { printWithContext() } }
8. Kotlin 1.9+ 8.1 多平台改进
语法说明 :
使用 expect
和 actual
定义跨平台代码。
应用场景 :
底层原理 :
示例代码 :
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 编译器特性
语法说明 :
应用场景 :
底层原理 :
示例代码 :
注意事项 :
三、其他特性 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 ) 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
1 2 3 4 5 import java.io.Filefun main () { File("test.txt" ).writeText("Hello" ) println(File("test.txt" ).readText()) }
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
1 2 3 4 fun main () { val ref = String::class println (ref.simpleName) }
注意事项 :
性能 :反射开销大。
类型 :区分 ::class
和 ::class.java
。
2.2 函数引用:::function
1 2 3 4 5 fun hello () = println("Hello" )fun main () { val ref = ::hello ref() }
注意事项 :
适用性 :仅限顶层或成员函数。
性能 :避免频繁创建。
2.3 反射库:kotlin.reflect
语法说明 :
使用 kotlin.reflect
访问类、属性等。
应用场景 :
底层原理 :
示例代码 :
1 2 3 4 5 6 import kotlin.reflect.full.memberPropertiesdata class Person (val name: String)fun main () { val props = Person::class .memberProperties println(props.map { it.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.Delegatesfun main () { val lazyVal: String by lazy { println("Computed" ) "Lazy" } println(lazyVal) println(lazyVal) var obsVal: String by Delegates.observable("Init" ) { property, old, new -> println("${property.name} : $old -> $new " ) } obsVal = "New" obsVal = "Final" }
注意事项 :
lazy
线程安全 :默认同步,需明确模式(如 LazyThreadSafetyMode.NONE
)。
observable
开销 :每次赋值触发回调,注意性能。
初始化 :lazy
不可重新赋值。
3.2 类委托: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 printerfun main () { val delegator = Delegator(PrinterImpl()) delegator.print() }
注意事项 :
覆盖 :委托后仍可重写方法。
依赖 :确保委托对象可靠。