ПрограммированиеAndroid разработчик / Backend разработчик

Как работает инициализация константных значений (const val) и compile-time констант в Kotlin? В чем отличие от обычного val, какие есть ограничения, как используется для аннотаций и почему не всегда можно использовать const val там, где хочется?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В Kotlin ключевое слово const val используется для объявления compile-time констант, т.е. значений, известных и вычисляемых на этапе компиляции.

  • const val доступно только для top-level переменных, либо для свойств, объявленных object-объектов или companion object.
  • Значение должно быть типов: String, числовые примитивы или Boolean.
  • Используется для аннотаций и декораторов, где значение должно быть подставлено на этапе компиляции.

val — это неизменяемая переменная, но значение может быть задано во время выполнения, что допускает вычисления или вызовы функций при инициализации:

val timestamp = System.currentTimeMillis() // Это НЕ const val const val APP_NAME = "MyApp" // Это compile-time константа

В аннотациях можно использовать только const val, пример:

const val AUTHOR = "John Doe" @Target(AnnotationTarget.CLASS) annotation class Author(val name: String) @Author(AUTHOR) class Example

Если попытаться использовать val в таких случаях, будет ошибка компиляции.


Вопрос с подвохом

Почему нельзя объявить const val внутри обычного класса?

Ответ: Потому что const val требует, чтобы переменная была доступна на этапе компиляции, а переменные экземпляра класса инициализируются только во время создания объекта, поэтому они не могут быть compile-time константами.

class Example { // Ошибка! Нельзя так // const val CLASS_NAME = "MyClass" }

История

Cломалась сборка из-за того, что разработчик попытался передать вычисленное на момент исполнения значение через аннотацию.

Разработчик объявил:

val version = getVersionFromConfig() @Target(AnnotationTarget.CLASS) annotation class Version(val value: String) @Version(version) class App

Проект не компилировался, т.к. только const val можно использовать в аргументах аннотаций!


История

Ошибка на Android: попытка использовать локальные переменные как константные ключи в Intent.

class Keys { companion object { val EXTRA_USER_ID = "userId" } } intent.putExtra(Keys.EXTRA_USER_ID, userId)

В некоторых инструментах или фреймворках ожидается const val, а не обычный val — иначе IDE или ресурсы Android не видят эти значения как compile-time константы.


История

Использование неподходящего типа для const val.

const val LIST = listOf(1,2,3) // Ошибка! Только примитивы и String.

Незнание ограничений типов привело к ошибке компиляции и потере времени.