Kotlin const vs val: в чем разница и что выбрать?

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Kotlin const vs val: в чем разница и что выбрать?

Вы пишете код на Kotlin и вдруг задумываетесь: «А в чем, собственно, разница между const и val? Оба ведь вроде бы неизменяемые?». Отличный вопрос! Этот момент сбивает с толку даже опытных разработчиков, переходящих с Java или других языков. Неудивительно, что на Stack Overflow тема «What is the difference between "const" and "val"?» набирает тысячи просмотров. Сегодня мы раз и навсегда разберемся в этом вопросе, разложим по полочкам теорию и подкрепим все живыми примерами кода.

Готовы? Поехали!

Краткий ликбез: что такое val?

Начнем с самого простого. val (от слова value — значение) — это неизменяемая ссылка. Вы можете присвоить ей значение один раз и больше никогда не менять. Звучит знакомо? Да, это аналог final в Java или readonly в C#.

val name: String = "Алиса"
name = "Боб" // Ошибка компиляции! Val cannot be reassigned

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

val numbers = mutableListOf(1, 2, 3)
numbers.add(4) // Работает!
// numbers = mutableListOf(5, 6) // Ошибка! Нельзя переназначить ссылку

val может быть инициализирован как во время объявления, так и позже в коде (например, в конструкторе или блоке init). Его значение вычисляется во время выполнения программы (runtime).

А что такое const? Строгий страж времени компиляции

const — это более строгий брат val. Он тоже неизменяемый, но с суперспособностью: значение должно быть известно на этапе компиляции (compile-time). Другими словами, это настоящая константа, которую компилятор может подставить прямо в код, как встроенную.

У const есть жесткие правила:

  • Может быть объявлен только на уровне файла (вне класса) или внутри object / companion object.
  • Должен быть примитивного типа или типа String.
  • Не может быть результатом вызова функции или вычисления — только литерал или другая константа.
// Правильно
const val PI = 3.14159
const val APP_NAME = "MyApp"

// Неправильно
const val currentTime = System.currentTimeMillis() // Ошибка! Значение не известно на этапе компиляции
const val userName = getName() // Ошибка! Вызов функции недопустим

Главные отличия: const vs val в таблице

Чтобы было наглядно, вот сравнительная таблица:

Критерий const val val
Время инициализации На этапе компиляции На этапе выполнения
Где можно объявить Топ-уровень, object, companion object Где угодно (внутри класса, функции, конструктора)
Типы данных Только примитивы и String Любые типы (включая объекты, списки)
Производительность Максимальная (инлайнинг) Стандартная
Использование в аннотациях Да Нет

Практический пример: аннотации и производительность

Одно из самых частых применений const — это аннотации. В Kotlin параметры аннотаций должны быть известны на этапе компиляции. Попробуйте использовать val — и компилятор выдаст ошибку.

// Так работает
const val API_ENDPOINT = "https://api.example.com"
@Deprecated(API_ENDPOINT) // OK

// Так не работает
val apiEndpoint = "https://api.example.com"
@Deprecated(apiEndpoint) // Ошибка! 'apiEndpoint' is not a compile-time constant

Еще один бонус const — производительность. Компилятор встраивает значение константы прямо в байт-код, а не создает поле класса. Это особенно заметно, если константа используется много раз. Пример:

// Kotlin код
const val MAX_RETRIES = 3

fun retry() {
    repeat(MAX_RETRIES) { ... }
}

// После компиляции в Java будет что-то вроде:
// repeat(3) { ... } — значение подставлено напрямую

Когда использовать const, а когда val?

Вот простая шпаргалка:

  • Используйте const val, если:
    • Значение известно до запуска программы (например, математические константы, URL-адреса, названия приложений).
    • Константа используется в аннотациях.
    • Вы хотите максимальную производительность и минимизировать накладные расходы.
  • Используйте val, если:
    • Значение вычисляется во время выполнения (результат функции, ввод пользователя, текущее время).
    • Константа находится внутри класса или функции.
    • Тип данных не примитив и не String (например, объект, список, Map).

Жизненный пример: приложение для заметок

Представьте, что вы пишете простое приложение для заметок на Kotlin. Где пригодятся const и val?

// Константы на уровне файла — идеально для const
const val DATABASE_NAME = "notes.db"
const val MAX_TITLE_LENGTH = 50

class Note(val title: String, val content: String) {
    // Это val — значение задается в конструкторе, но не const
    val createdAt: Long = System.currentTimeMillis()

    companion object {
        // Константа внутри companion object — тоже const
        const val NOTE_TYPE = "text"
    }

    fun validate(): Boolean {
        // Локальная val — вычисляется на ходу
        val isValid = title.length <= MAX_T                

Блоги

Рекомендаций по книгам