Глиф Учебники

Урок 2. Переменные val и var, типы данных

Курс «Kotlin» · урок 2 из 10 · 4 минуты чтения

Программе нужно где-то хранить данные: имя пользователя, счёт в игре, цену товара. Для этого есть переменные — именованные ячейки, в которых лежат значения. В этом уроке — как их объявлять, какие бывают типы и как считать.

val и var

В Kotlin переменную объявляют одним из двух слов:

Kotlin
fun main() {
    val name = "Anna"
    var age = 20
    println(name)
    println(age)
    age = 21
    println(age)
}
Вывод
Anna
20
21

Знак = здесь — не равенство, а присваивание: «положить в переменную значение справа». Если написать name = "Olga", программа не соберётся: компилятор сообщит, что val нельзя присвоить заново (val cannot be reassigned).

val — один раз val name = "Anna" name "Anna" name = "Olga" не соберётся val cannot be reassigned var — можно менять var age = 20 age = 21 age 20 было 21 стало
Переменную val нельзя присвоить заново — name = "Olga" не соберётся, а var age можно менять: было 20, стало 21.

Какое слово выбирать? По умолчанию — val. Когда значение не меняется, программу проще читать: не нужно искать, где его могли изменить. var берите только тогда, когда значение действительно меняется — например, счётчик в цикле. Подробнее — в справке Чем val отличается от var.

Типы данных

У каждой переменной есть тип — какие значения в ней могут лежать. Основные:

ТипЧто хранитПример
Intцелое число от −2 147 483 648 до 2 147 483 64742, -7
Longбольшое целое число, примерно до 9·10¹⁸9_000_000_000L
Doubleдробное число3.14, -0.5
Booleanлогическое значение: да или нетtrue, false
Charодин символ, в одинарных кавычках'A', '7'
Stringстрока — текст, в двойных кавычках"Hello"

Тип можно не писать: компилятор сам поймёт его по значению. Это называется выводом типа. Но его можно указать явно — через двоеточие после имени:

Kotlin
fun main() {
    val count: Int = 5
    val price: Double = 9.99
    val isOpen: Boolean = true
    val letter: Char = 'K'
    val city: String = "Minsk"
    val population = 2_000_000
    println(count)
    println(price)
    println(isOpen)
    println(letter)
    println(city)
    println(population)
}
Вывод
5
9.99
true
K
Minsk
2000000

Подчёркивания в числах — только для удобства чтения: 2_000_000 — то же, что 2000000. Дробная часть отделяется точкой, не запятой: 9.99.

Тип переменной задаётся один раз и не меняется. В var age = 20 можно положить 21, но не "twenty": компилятор сообщит о несовпадении типов (type mismatch).

Арифметика

Kotlin
fun main() {
    val a = 17
    val b = 5
    println(a + b)
    println(a - b)
    println(a * b)
    println(a / b)
    println(a % b)
    println(a.toDouble() / b)
}
Вывод
22
12
85
3
2
3.4

Главное, что здесь нужно запомнить: деление двух целых чисел даёт целое число, дробная часть отбрасывается. 17 / 5 — это 3, а не 3.4. Знак % даёт остаток от деления: 17 % 5 — 2. Чтобы получить дробный результат, хотя бы одно из чисел должно быть дробным: 17.0 / 5 или a.toDouble() / b.

17 / 5 целое деление 3 17 % 5 остаток 2 17.0 / 5 дробное деление 1 2 3 0.4 3.4
17 предметов по 5: целое деление 17 / 5 даёт 3 полные группы, остаток 17 % 5 — это 2, а 17.0 / 5 даёт дробное 3.4.

Для изменения переменной есть короткие записи:

ЗаписьТо же самое
x += 3x = x + 3
x -= 3x = x - 3
x *= 2x = x * 2
x++x = x + 1
x--x = x - 1

Все они работают только с var.

Перевод из типа в тип

Kotlin сам не превращает переменную одного числового типа в другой — даже Int в Long, хотя любое Int поместится в Long. Строка val big: Long = n при val n = 7 не соберётся. (Число, записанное прямо в коде, подстраивается под тип само: val big: Long = 7 — можно.) Перевод пишут явно:

Kotlin
fun main() {
    val n = 7
    val big: Long = n.toLong()
    val d = n.toDouble()
    val back = 3.99.toInt()
    println(big)
    println(d)
    println(back)
    println(n.toString() + "!")
}
Вывод
7
7.0
3
7!

Дробное число выводится с точкой и хотя бы одной цифрой после неё: 7.0, а не 7.

Перевод строки в число ("42".toInt()) разобран в следующем уроке и в справке Как перевести строку в число.

Переполнение

У Int есть предел. Если результат за него выходит, число «переворачивается» и становится отрицательным, причём без всякой ошибки:

Kotlin
fun main() {
    val big = 2_000_000_000
    println(big + big)
    println(big.toLong() + big)
}
Вывод
-294967296
4000000000
0 2 147 483 647 −2 147 483 648 Int + 2 000 000 000 2 000 000 000 −294 967 296 val big = 2_000_000_000 big + big Int: -294967296 вышло за предел — без ошибки big.toLong() + big Long: 4000000000 предел Long — около 9·10¹⁸
Значения Int идут по кругу: big + big проходит верхний предел и без ошибки даёт -294967296, а big.toLong() + big даёт 4000000000.

Если числа могут быть больше двух миллиардов (суммы денег в копейках, факториалы, время в миллисекундах), берите Long. Число, которое не помещается в Int, компилятор сам делает Long: у val x = 3_000_000_000 тип Long.

Строки и символы

Строки складываются знаком +. К строке можно прибавить число — оно станет текстом:

Kotlin
fun main() {
    val word = "Kot" + "lin"
    println(word)
    println(word.length)
    println("Age: " + 20)
}
Вывод
Kotlin
6
Age: 20

length — длина строки в символах. Обратный порядок, 20 + " years", не соберётся: к числу строку прибавить нельзя. Удобнее всего вставлять значения в текст через строковые шаблоны — о них в следующем уроке.

Char и String — разные типы: 'A' — один символ, "A" — строка из одного символа.

Константы

Значение, которое известно заранее и нужно в разных местах программы, объявляют вне функций как const val:

Kotlin
const val MAX_SCORE = 100

fun main() {
    println(MAX_SCORE)
}
Вывод
100

Имена констант принято писать большими буквами через подчёркивание. Обычные переменные — в стиле camelCase: первое слово с маленькой буквы, следующие с большой: userName, totalPrice.

Коротко

Проверьте себя

1. Чем val отличается от var?
2. Что выведет println(7 / 2)?
3. Чему равно 3.99.toInt()?
4. Какой тип выбрать для числа 5 000 000 000?
5. Что выведет программа?
Kotlin
fun main() {
    var x = 10
    x += 5
    x--
    println(x)
}