В Kotlin, если вы не хотите инициализировать свойство класса внутри конструктора или в верхней части тела класса, у вас есть в основном эти две опции (из ссылки на язык):
lazy () - это функция, которая принимает лямбду и возвращает экземпляр Lazy, который может служить делегатом для реализации свойства lazy: первый вызов get () выполняет лямбду, переданную в lazy (), и запоминает результат, последующие вызовы get () просто возвращает запомненный результат.
пример
public class Hello { val myLazyString: String by lazy { "Hello" } }
Поэтому первый вызов и subquential звонков, где бы оно, к myLazyString вернется «Hello»
Обычно свойства, объявленные как имеющие ненулевой тип, должны быть инициализированы в конструкторе. Однако довольно часто это не удобно. Например, свойства могут быть инициализированы посредством внедрения зависимости или в методе настройки модульного теста. В этом случае вы не можете предоставить ненулевой инициализатор в конструкторе, но вы все равно хотите избегать нулевых проверок при обращении к свойству внутри тела класса.
Чтобы справиться с этим случаем, вы можете пометить свойство модификатором lateinit:
public class MyTest { lateinit var subject: TestSubject @SetUp fun setup() { subject = TestSubject() } @Test fun test() { subject.method() } }
Модификатор можно использовать только для свойств var, объявленных внутри тела класса (не в основном конструкторе), и только в том случае, если у свойства нет пользовательского метода получения или установки. Тип свойства должен быть ненулевым, и это не должен быть примитивный тип.
Итак, как правильно выбрать один из этих двух вариантов, поскольку оба они могут решить одну и ту же проблему?
источник
lateinit
его фоновом поле отображается видимость сеттера, поэтому способы доступа к свойству из Kotlin и из Java различны. А из кода Java это свойство может быть установлено дажеnull
без каких-либо проверок в Kotlin. Поэтомуlateinit
не для ленивой инициализации, а для инициализации не обязательно из кода Котлина.Lazy
+,.isInitialized()
чтобы сделать это. Я думаю, что нет простого способа проверить такую недвижимостьnull
из-за гарантии, которую вы не можете получитьnull
от нее. :) Смотрите это демо .by lazy
замедлить время сборки или выполнения?lateinit
чтобы обойти использованиеnull
для неинициализированной стоимости. Помимо этогоnull
никогда не следует использовать, и сlateinit
нулями могут быть устранены прочь. Вот так я люблю Котлина :)В дополнение к
hotkey
хорошему ответу, вот как я выбираю из двух на практике:lateinit
предназначен для внешней инициализации: когда вам нужен внешний материал для инициализации вашего значения путем вызова метода.например, позвонив:
Хотя
lazy
это когда он использует только внутренние зависимости вашего объекта.источник
Очень короткий и краткий ответ
lateinit: в последнее время инициализирует ненулевые свойства
В отличие от отложенной инициализации, lateinit позволяет компилятору распознавать, что значение ненулевого свойства не сохраняется на этапе конструктора для нормальной компиляции.
Ленивая инициализация
Функция lazy может быть очень полезна при реализации свойств только для чтения (val), которые выполняют ленивую инициализацию в Kotlin.
by lazy {...} выполняет свой инициализатор, где впервые используется определенное свойство, а не его объявление.
источник
латинит против ленивых
lateinit
я) Используйте его с изменяемой переменной [var]
ii) Допускается только с ненулевыми типами данных
iii) компилятору обещано, что значение будет инициализировано в будущем.
ПРИМЕЧАНИЕ . Если вы попытаетесь получить доступ к переменной lateinit без ее инициализации, она выдаст исключение UnInitializedPropertyAccessException.
ленивый
i) Ленивая инициализация была разработана, чтобы предотвратить ненужную инициализацию объектов.
ii) Ваша переменная не будет инициализирована, если вы ее не используете.
iii) Инициализируется только один раз. В следующий раз, когда вы его используете, вы получите значение из кеш-памяти.
iv) Это потокобезопасно (инициализируется в потоке, в котором оно используется впервые. Другие потоки используют то же значение, которое хранится в кэше).
v) Переменная может быть только val .
vi) Переменная может быть только ненулевой .
источник
В дополнение ко всем отличным ответам, существует концепция, называемая отложенной загрузкой:
Используя его правильно, вы можете сократить время загрузки вашего приложения. И способ его реализации Kotlin заключается в
lazy()
том, чтобы загружать необходимое значение в вашу переменную всякий раз, когда это необходимо.Но lateinit используется, когда вы уверены, что переменная не будет нулевой или пустой, и будет инициализирована, прежде чем использовать ее -eg в
onResume()
методе для android-, поэтому вы не хотите объявлять ее как обнуляемый тип.источник
onCreateView
,onResume
а другие -lateinit
, но иногда там возникали ошибки (потому что некоторые события начинались раньше). Так что, возможно,by lazy
может дать соответствующий результат. Я используюlateinit
для ненулевых переменных, которые могут меняться в течение жизненного цикла.Все правильно, но один из фактов простое объяснение LAZY ---- Бывают случаи, когда вы хотите отложить создание экземпляра вашего объекта до его первого использования. Этот метод известен как ленивая инициализация или ленивая реализация. Основная цель отложенной инициализации - повысить производительность и уменьшить объем используемой памяти. Если создание экземпляра вашего типа сопряжено с большими вычислительными затратами и программа может в конечном итоге фактически не использовать его, вы захотите отложить или даже не тратить циклы ЦП.
источник
Если вы используете контейнер Spring и хотите инициализировать необнуляемое поле компонента,
lateinit
лучше подойдет.источник
@Autowired lateinit var myBean: MyBean
Если вы используете неизменяемую переменную, лучше инициализировать с помощью
by lazy { ... }
илиval
. В этом случае вы можете быть уверены, что он всегда будет инициализирован при необходимости и не более 1 раза.Если вы хотите ненулевую переменную, которая может изменить ее значение, используйте
lateinit var
. В разработке Android вы можете позже инициализировать его в таких мероприятиях , какonCreate
,onResume
. Имейте в виду, что если вы вызовете запрос REST и получите доступ к этой переменной, это может привести к исключениюUninitializedPropertyAccessException: lateinit property yourVariable has not been initialized
, поскольку запрос может выполняться быстрее, чем инициализируется этой переменной.источник