В Kotlin существуют два разных подхода для поздней инициализации свойств: lateinit и lazy.
lateinit — модификатор, применяемый к переменным (var), которые будут инициализированы позже, обычно через DI или в инициализационном блоке. Подходит только для нестатических переменных НЕ nullable-
типов. Обращение до инициализации — выбрасывает исключение UninitializedPropertyAccessException.
class MyClass { lateinit var data: String fun init() { data = "Hello!" } }
lazy — специальный делегат, применяемый к val-свойствам (только read-only). Выражение-инициализатор вычисляется при первом обращении к переменной. Безопасно для многопоточного доступа по умолчанию.
val config: Config by lazy { loadConfigFromFile() }
lateinit не работает с типами примитивов и val.lazy не допускает переинициализации.lateinit — для переменных, которые гарантированно будут назначены позднее (например, через DI-фреймворк или во фрагменте жизненного цикла Android).lazy — для ленивых вычислений, когда значение дорого по вычислениям и может быть не востребовано.Можно ли использовать
lateinitдля свойств типа Int?
Ответ: Нет. lateinit работает только с объектными НЕ nullable-типами. Для примитивов и nullable-типов — нельзя. Попытка объявить lateinit var a: Int приведет к ошибке компиляции.
История
В образовательном проекте объявили переменную конфигурации как lateinit var config: Config?, но компилятор не разрешил это сделать — сэкономили время, но пришлось разобраться, почему работает не так, как ожидали.
История
В Android-приложении забыли проверить на инициализацию lateinit-свойства перед вызовом. Это привело к крашу приложения на проде — дизайнер пытался получить доступ к свойству до onCreateView. Помогли дополнительные проверки.
История
При использовании многопоточности разработчик применил by lazy для инициализации ресурсоемкого объекта без передачи параметра, посчитав, что делегат по умолчанию не потокобезопасен. В итоге в релизе появились проблемы с race condition. Решили через передачу соответствующего параметра для lazy: by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ... }.