Шпаргалка по Kotlin
Последнее обновление
Hello World и основы
Программа на Kotlin начинается с функции main верхнего уровня - класс не нужен.
| Синтаксис | Значение |
|---|---|
fun main() { println("Hello") } | Точка входа программы |
println("text") | Вывести строку в стандартный вывод |
print("text") | Вывести без перевода строки в конце |
// comment | Однострочный комментарий |
/* comment */ | Многострочный комментарий |
val input = readLine() | Прочитать строку из stdin (nullable String?) |
val line = readln() | Прочитать строку из stdin (non-null, 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', "текст" |
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 safety
Тип по умолчанию не допускает null; добавьте ?, чтобы разрешить null, и компилятор заставит его обработать.
| Синтаксис | Значение |
|---|---|
var s: String? = null | Nullable-тип |
s?.length | Безопасный вызов - вернёт null, если s равно null |
s?.length ?: 0 | Элвис-оператор - запасное значение при null |
s!!.length | Утверждение non-null - бросает исключение, если s равно null |
if (s != null) s.length | Smart cast к non-null внутри проверки |
s?.let { println(it) } | Выполнить блок только если не null |
val n = s?.toIntOrNull() | Разобрать или вернуть null при неверном вводе |
lateinit var x: String | Non-null переменная, инициализируемая позже |
Операторы
| Оператор | Значение |
|---|---|
+ - * / % | Арифметика (/ для Int - целочисленное деление) |
+= -= *= /= %= | Составное присваивание |
++ -- | Инкремент / декремент |
== != | Структурное равенство (вызывает equals) |
=== !== | Ссылочное равенство (тот же объект) |
< > <= >= | Сравнение |
&& || ! | Логические и / или / не |
a in 1..10 | Принадлежность диапазону или коллекции |
x as Int, x as? Int | Приведение / безопасное приведение (null при неудаче) |
x is String | Проверка типа (smart cast при успехе) |
Управление потоком (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 } | Сопоставить с типом (со smart cast) |
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 } | Лямбда в переменной |
fun String.shout() = uppercase() + "!" | Функция-расширение |
fun apply(f: (Int) -> Int) = f(2) | Функция как параметр |
list.map { it * 2 } | Trailing-лямбда, 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) | Маленькие кортежи фиксированного размера |
Мапы и множества
| Синтаксис | Значение |
|---|---|
val m = mapOf("a" to 1, "b" to 2) | Мапа только для чтения |
val mm = mutableMapOf<String, Int>() | Изменяемая мапа |
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>() | Изменяемое множество |
Операции над коллекциями (лямбды)
| Синтаксис | Значение |
|---|---|
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() } | Преобразовать и сгладить |
Классы и data-классы
| Синтаксис | Значение |
|---|---|
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 } | Enum |
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 { ... } | Идиоматичная проверка на null + использование |
Весь синтаксис Kotlin, который вы ищете, на одной странице. Эта шпаргалка по Kotlin - краткий справочник по языку Android и значительной части современной JVM: объявление переменных, безопасная работа с null, ветвление через when, обход диапазонов, написание функций и работа со списками и мапами.
Всё здесь - стандартный Kotlin, одинаково работающий на JVM, в Android и в Kotlin Multiplatform. Копируйте нужное или пробуйте вживую в Kotlin-плейграунде: вставьте фрагмент, нажмите Run и посмотрите вывод в браузере.
Вопросы о шпаргалке по Kotlin
Эта шпаргалка по Kotlin бесплатна?
when, оператор null safety или метод коллекции.В чём разница между val и var в Kotlin?
val объявляет ссылку только для чтения: она присваивается один раз и не может быть переприсвоена. var объявляет изменяемую переменную, которую можно переприсваивать. Учтите, что val фиксирует только ссылку: в val list = mutableListOf(1) всё ещё можно добавлять элементы. Стиль Kotlin - использовать val везде и переходить на var только там, где переприсваивание действительно нужно.Как работает null safety в Kotlin?
String никогда не содержит null, а String? может. Компилятор не даст вызвать метод у nullable-значения без обработки случая null: безопасный вызов (s?.length), запасное значение через Элвис-оператор (s?.length ?: 0), проверка на null со smart cast (if (s != null)) или, в крайнем случае, утверждение s!!, которое бросает NullPointerException, если значение действительно null.Когда использовать when вместо if в Kotlin?
when, когда сравниваете одно значение с несколькими вариантами - константами, диапазонами, типами или их смесью, а if/else - для одного условия да/нет. Оба являются выражениями, поэтому val label = when (x) { ... } и val label = if (c) a else b одинаково идиоматичны. when как выражение должен быть исчерпывающим, что обычно означает ветку else (sealed-классы и enum могут обходиться без неё).Можно ли практиковаться в Kotlin онлайн?
when, циклы, функции и коллекции и выдаст бесплатный сертификат в конце.