Переменные: val и var

Учимся хранить данные: что выбрать — val или var.

val объявляет переменную, которую нельзя переприсвоить (read-only), а var — переменную, значение которой можно менять.

Любая программа хранит данные в переменных. В Kotlin есть два ключевых слова для их объявления, и выбор между ними — это выбор между неизменяемостью и изменяемостью.

val против var

val (от value) — переменная только для чтения: присвоить ей значение можно один раз. var (от variable) — обычная переменная, которую можно переприсваивать.

fun main() {
    val name = "Аня"   // нельзя переприсвоить
    var age = 25       // можно менять
    age = 26
    println("$name, $age")
    // name = "Боря"   // ОШИБКА компиляции
}

Вывод:

Аня, 26

Вывод типов

Обратите внимание: мы не писали тип переменной. Kotlin сам определил, что name — это String, а ageInt. Это называется вывод типов (type inference). При желании тип можно указать явно — это обязательно, когда значение не присваивается сразу.

fun main() {
    val pi: Double = 3.14
    val count: Int = 10
    val letter: Char = 'A'
    val flag: Boolean = true
    println("$pi $count $letter $flag")
}

Вывод:

3.14 10 A true

Почему предпочитают val

Хороший стиль в Kotlin — объявлять переменные через val и переходить на var только при реальной необходимости. Неизменяемые данные проще понимать (значение не «убежит» из-под ног), безопаснее в многопоточности и реже становятся источником багов. Если значение присваивается один раз — это val.

Как работает под капотом

Важно различать неизменяемость ссылки и неизменяемость объекта. val запрещает только переприсвоить саму переменную, но если внутри лежит изменяемый объект (например, MutableList), его содержимое менять можно.

fun main() {
    val list = mutableListOf(1, 2)
    list.add(3)        // можно: меняем содержимое
    // list = mutableListOf()  // нельзя: переприсвоение val
    println(list)
}

Вывод:

[1, 2, 3]

Частые ошибки

  • Использовать var по привычке. Это снижает безопасность кода; начинайте с val.
  • Думать, что val делает объект неизменяемым. Неизменна только ссылка, а содержимое изменяемого объекта — нет.
  • Забывать тип при отложенном присваивании. Если значение не задано сразу, тип нужно указать явно.

Итог

  • val — read-only, var — изменяемая переменная.
  • Kotlin выводит тип автоматически, но его можно указать явно.
  • Предпочитайте val: меньше ошибок и проще читать.
  • val фиксирует ссылку, но не «замораживает» содержимое объекта.
Проверьте себя
1. Чем отличается val от var?
Aval быстрее работает, var медленнее
Bval нельзя переприсвоить, var можно
Cval только для чисел, var для строк
DМежду ними нет разницы
2. Что произойдёт с кодом: val list = mutableListOf(1, 2); list.add(3)?
AОшибка компиляции: list объявлен через val
BСписок станет [1, 2, 3] — содержимое менять можно
CСписок останется [1, 2]
DПрограмма упадёт во время выполнения
3. Когда тип переменной нужно указывать явно?
AВсегда
BНикогда — Kotlin сам выведет
CКогда значение не присваивается сразу при объявлении
DТолько для строк