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

Чем val отличается от var

Справочник · Kotlin · 1 минута чтения

Kotlin
fun main() {
    val city = "Minsk"
    var visits = 1
    visits = visits + 1
    println("$city: $visits")
}
Вывод
Minsk: 2

Строка city = "Brest" в этой программе не соберётся: компилятор ответит, что val нельзя присвоить заново (val cannot be reassigned). Исправление — либо объявить переменную через var, либо, что чаще правильнее, завести новую: val newCity = "Brest".

Что выбирать

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

Тип у обоих задаётся один раз: в var visits = 1 можно положить другое число, но не строку.

val не значит «содержимое не меняется»

val запрещает положить в переменную другой объект, но не менять сам объект:

Kotlin
fun main() {
    val items = mutableListOf("bread")
    items.add("milk")
    println(items)
}
Вывод
[bread, milk]

Это работает: список тот же, изменилось его содержимое. А items = mutableListOf() уже не соберётся. Чтобы содержимое тоже было неизменным, берите список только для чтения — listOf(...).

val и const val

valconst val
Где объявляетсягде угодновне функций, в object или companion object
Значениелюбое, можно посчитать при запускеизвестно при сборке программы: число, строка, true/false
Примерval now = System.currentTimeMillis()const val MAX_USERS = 100

const val — настоящая константа: компилятор подставляет её значение прямо в код. Для неё значение должно быть записано в программе или посчитано из других констант.

Отложенное присваивание

Объявить val и присвоить позже можно, но только один раз и до первого использования:

Kotlin
fun main() {
    val n = 7
    val parity: String
    if (n % 2 == 0) {
        parity = "even"
    } else {
        parity = "odd"
    }
    println(parity)
}
Вывод
odd

Компилятор проверяет, что значение присвоено ровно один раз на любом пути программы. Короче то же самое пишется через if-выражение: val parity = if (n % 2 == 0) "even" else "odd".

Для свойств класса, которые получают значение не в конструкторе, а позже, есть lateinit var — о нём в справке lateinit — отложенная инициализация.

Сравнение с Java

val в Kotlin — это final переменная в Java, а var — обычная. Разница в том, что в Kotlin val пишется так же коротко, как var, поэтому неизменяемые переменные становятся привычкой.