Menu
CoddyTech

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, Stringtrue/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 ?: 0Elvis 运算符:为 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、循环、函数和集合,学完还能免费获得证书。
Coddy 编程语言插图

在 Coddy 学习 Kotlin

开始