Kotlin 速查表
最后更新
Hello World 与基础
Kotlin 程序从顶层的 main 函数开始运行,不需要写类。
| 语法 | 含义 |
|---|---|
fun main() { println("Hello") } | 程序的入口点 |
println("text") | 向标准输出打印一行 |
print("text") | 打印,末尾不换行 |
// comment | 单行注释 |
/* comment */ | 多行注释 |
val input = readLine() | 从标准输入读取一行(可空的 String?) |
val line = readln() | 从标准输入读取一行(非空,Kotlin 1.6+) |
变量(val / var)与类型
优先用 val,只有值确实需要改变时才用 var。
| 语法 | 含义 |
|---|---|
val name = "Ada" | 只读变量,类型推断为 String |
var count = 0 | 可变变量 |
val age: Int = 30 | 显式标注类型 |
Int, Long, Double, Float | 数值类型(42、42L、3.14、3.14f) |
Boolean, Char, String | true/false, 'a', "text" |
val big = 1_000_000 | 用下划线让字面量更易读 |
"3".toInt(), "2.5".toDouble() | 把字符串解析成数字 |
42.toString() | 数字转字符串 |
const val MAX = 10 | 编译期常量(写在顶层或 object 中) |
字符串与模板
几乎所有需要拼接字符串的地方,都可以用字符串模板代替。
| 语法 | 含义 |
|---|---|
"Hi, $name" | 把变量插入字符串 |
"Total: ${price * qty}" | 插入表达式 |
s.length | 字符个数 |
s.uppercase(), s.lowercase() | 转换大小写 |
s.trim() | 去掉首尾空白字符 |
s.contains("x"), s.startsWith("a") | 在字符串中查找 |
s.substring(0, 3) | 按索引范围截取 |
s.split(",") | 拆分成 List<String> |
s[0] | 某个索引处的字符 |
"""raw text""" | 原始多行字符串,无需转义 |
"%.2f".format(3.14159) | 格式化输出(3.14) |
空安全
类型默认不可为空;加上 ? 才允许 null,编译器会要求你处理这种情况。
| 语法 | 含义 |
|---|---|
var s: String? = null | 可空类型 |
s?.length | 安全调用:s 为 null 时返回 null |
s?.length ?: 0 | Elvis 运算符:为 null 时使用备用值 |
s!!.length | 非空断言:s 为 null 时抛出异常 |
if (s != null) s.length | 检查之后自动智能转换为非空类型 |
s?.let { println(it) } | 只在不为 null 时执行代码块 |
val n = s?.toIntOrNull() | 解析字符串,输入不合法时返回 null |
lateinit var x: String | 稍后再初始化的非空 var |
运算符
| 运算符 | 含义 |
|---|---|
+ - * / % | 算术运算(两个 Int 相除 / 是整数除法) |
+= -= *= /= %= | 复合赋值 |
++ -- | 自增 / 自减 |
== != | 结构相等(调用 equals) |
=== !== | 引用相等(同一个对象) |
< > <= >= | 比较 |
&& || ! | 逻辑与 / 或 / 非 |
a in 1..10 | 判断是否在区间或集合中 |
x as Int, x as? Int | 类型转换 / 安全转换(失败时返回 null) |
x is String | 类型检查(成功后自动智能转换) |
流程控制(if / when)
if 和 when 都是表达式,会返回一个值。
| 语法 | 含义 |
|---|---|
if (a > b) x else y | 把 if 当表达式用(Kotlin 没有 ?: 三元运算符) |
if (c) { ... } else if (d) { ... } else { ... } | 多个分支串联 |
when (x) { 1 -> "one"; 2 -> "two"; else -> "other" } | 匹配一个值 |
when (x) { 1, 2 -> "low" } | 一个分支匹配多个值 |
when (x) { in 1..9 -> "digit" } | 匹配一个区间 |
when (x) { is String -> x.length } | 匹配类型(带智能转换) |
when { x < 0 -> "neg"; x == 0 -> "zero"; else -> "pos" } | 不带参数的 when,相当于 if/else if |
val label = when (x) { ... } | 把 when 当表达式用(必须有 else) |
循环与区间
| 语法 | 含义 |
|---|---|
for (i in 1..5) | 闭区间 1 到 5 |
for (i in 1 until 5) | 1 到 4(不含结束值) |
for (i in 0..<5) | 效果同上,开区间写法(Kotlin 1.9+) |
for (i in 10 downTo 1 step 2) | 按步长倒数 |
for (item in list) | 遍历集合 |
for ((i, item) in list.withIndex()) | 同时拿到索引和元素 |
for (ch in "abc") | 遍历字符串中的字符 |
while (cond) { ... } | 条件为真时一直循环 |
do { ... } while (cond) | 至少执行一次 |
break, continue | 退出循环 / 跳到下一次迭代 |
repeat(3) { println(it) } | 把代码块执行 n 次 |
函数
| 语法 | 含义 |
|---|---|
fun add(a: Int, b: Int): Int { return a + b } | 声明函数 |
fun add(a: Int, b: Int) = a + b | 单表达式函数,返回类型自动推断 |
fun greet(name: String = "world") | 参数默认值 |
greet(name = "Ada") | 命名参数 |
fun log(vararg items: String) | 可变数量的参数 |
fun say(): Unit | 无返回值(Unit 可以省略) |
val square = { x: Int -> x * x } | 存放在变量中的 Lambda |
fun String.shout() = uppercase() + "!" | 扩展函数 |
fun apply(f: (Int) -> Int) = f(2) | 把函数作为参数 |
list.map { it * 2 } | 尾随 Lambda,it 代表唯一的参数 |
列表
listOf 是只读的;mutableListOf 可以修改。
| 语法 | 含义 |
|---|---|
val nums = listOf(1, 2, 3) | 只读列表 |
val items = mutableListOf("a") | 可变列表 |
nums[0], nums.first(), nums.last() | 访问元素 |
nums.getOrNull(9) | 安全访问,越界时返回 null |
items.add("b"), items.remove("a") | 添加 / 删除 |
items[0] = "z" | 按索引替换 |
nums.size, nums.isEmpty() | 大小和是否为空 |
x in nums, nums.contains(x) | 是否包含某元素 |
nums.indexOf(2) | 元素的位置,不存在时为 -1 |
nums.subList(0, 2) | 截取子列表(不含结束索引) |
nums.take(2), nums.drop(1) | 取前 n 个 / 去掉前 n 个 |
nums.sorted(), nums.reversed() | 返回排序后 / 反转后的新列表 |
nums.sum(), nums.average(), nums.maxOrNull() | 求和、平均值、最大值 |
nums.joinToString(", ") | 连接成一个字符串 |
Pair(1, "a"), 1 to "a", Triple(1, 2, 3) | 固定大小的小元组 |
Map 与 Set
| 语法 | 含义 |
|---|---|
val m = mapOf("a" to 1, "b" to 2) | 只读 map |
val mm = mutableMapOf<String, Int>() | 可变 map |
m["a"] | 按键查找(不存在时为 null) |
m.getOrDefault("z", 0) | 查找,不存在时返回备用值 |
mm["c"] = 3 | 插入或更新 |
for ((k, v) in m) | 用解构遍历键值对 |
m.keys, m.values | 所有键 / 所有值 |
"a" in m | 是否包含某个键 |
val s = setOf(1, 2, 2) | 元素不重复的集合({1, 2}) |
mutableSetOf<Int>() | 可变 set |
集合操作(Lambda)
| 语法 | 含义 |
|---|---|
list.map { it * 2 } | 转换每个元素 |
list.filter { it > 2 } | 保留符合条件的元素 |
list.forEach { println(it) } | 对每个元素执行操作 |
list.any { it > 2 }, list.all { it > 0 } | 是否有任一 / 全部元素符合条件 |
list.count { it % 2 == 0 } | 统计符合条件的个数 |
list.find { it > 2 } | 第一个符合条件的元素,没有则为 null |
list.sortedBy { it.length } | 按某个键排序 |
list.groupBy { it.first() } | 分组成一个 Map |
list.distinct() | 去重 |
list.fold(0) { acc, x -> acc + x } | 带初始值的归约 |
list.zip(other) | 把两个列表两两配对 |
list.flatMap { it.toList() } | 先映射再展平 |
类与数据类
| 语法 | 含义 |
|---|---|
class User(val name: String, var age: Int) | 带主构造函数和属性的类 |
val u = User("Ada", 36) | 创建实例(不用 new) |
u.name, u.age = 37 | 读取 / 修改属性 |
data class Point(val x: Int, val y: Int) | 自动生成 equals、hashCode、toString、copy |
p.copy(y = 5) | 复制并修改部分属性 |
val (x, y) = p | 解构声明 |
open class Base, class Sub : Base() | 继承(类默认是 final 的) |
override fun toString() = "..." | 重写成员 |
object Config { val debug = true } | 单例 |
companion object { fun create() = User("", 0) } | 类似静态成员 |
enum class Color { RED, GREEN } | 枚举 |
sealed class Result | 受限的类层次结构,在 when 中可穷举 |
interface Shape { fun area(): Double } | 接口 |
错误处理
| 语法 | 含义 |
|---|---|
try { ... } catch (e: Exception) { ... } | 捕获异常 |
try { ... } finally { ... } | 总会执行清理代码 |
val n = try { s.toInt() } catch (e: NumberFormatException) { 0 } | 把 try 当表达式用 |
throw IllegalArgumentException("bad") | 抛出异常 |
require(x > 0) { "x must be positive" } | 检查参数(抛出 IllegalArgumentException) |
check(ready) { "not ready" } | 检查状态(抛出 IllegalStateException) |
s.toIntOrNull() | 返回 null,不抛异常 |
runCatching { risky() }.getOrDefault(0) | 把调用结果包装成 Result |
作用域函数
五个小工具,用来在代码块中操作某个对象。
| 语法 | 含义 |
|---|---|
x.let { it + 1 } | it 指向对象,返回代码块的结果 |
x.run { this + 1 } | this 指向对象,返回代码块的结果 |
x.apply { field = 1 } | this 指向对象,返回对象本身 |
x.also { println(it) } | it 指向对象,返回对象本身 |
with(x) { field } | 不是扩展函数;this 指向 x,返回代码块的结果 |
x?.let { ... } | 地道的写法:先判空再使用 |
你会用到的每一种 Kotlin 语法,全都在这一页。Kotlin 是 Android 和大量现代 JVM 项目背后的语言,这份 Kotlin 速查表就是它的快速参考:声明变量、安全地处理 null、用 when 写分支、遍历区间、编写函数,以及使用列表和 map。
这里的内容都是标准 Kotlin,在 JVM、Android 和 Kotlin Multiplatform 上都能运行。需要什么就复制什么,也可以在 Kotlin 在线编辑器里直接试:粘贴代码片段,点击“运行”,就能在浏览器里看到输出。
Kotlin 速查表常见问题
这份 Kotlin 速查表免费吗?
免费。这份 Kotlin 速查表完全免费,也不用注册。把它加入书签,需要查
when 分支、空安全运算符或集合方法时随时回来看。Kotlin 中 val 和 var 有什么区别?
val 声明只读引用:只能赋值一次,不能重新赋值。var 声明可变变量,可以重新赋值。注意,val 固定的只是引用本身,val list = mutableListOf(1) 仍然可以往里添加元素。Kotlin 的惯用风格是处处用 val,只有真正需要重新赋值时才改用 var。Kotlin 的空安全是怎么工作的?
类型默认不可为空,所以
String 永远不能存 null,而 String? 可以。对可空值调用方法前,编译器会要求你先处理 null 的情况:用安全调用(s?.length)、Elvis 备用值(s?.length ?: 0)、会触发智能转换的判空(if (s != null)),或者万不得已时用非空断言 s!!,如果值真的是 null,它会抛出 NullPointerException。Kotlin 中什么时候用 when,什么时候用 if?
当你要把一个值和多种可能(常量、区间、类型或它们的组合)逐一比较时,用
when;只有一个“是或否”的条件时,用 if/else。两者都是表达式,所以 val label = when (x) { ... } 和 val label = if (c) a else b 都是地道的写法。当作表达式使用的 when 必须覆盖所有情况,通常意味着要加一个 else 分支(密封类和枚举不加也能穷举)。可以在线练习 Kotlin 吗?
可以。打开 Kotlin 在线编辑器,就能在浏览器里运行这份速查表中的任何代码片段,无需安装 JDK 或 IntelliJ。想系统地学,Coddy 的免费交互式 Kotlin 课程会带你从 Hello World 一路学到空安全、
when、循环、函数和集合,学完还能免费获得证书。