Почему поздняя инициализация var не может использоваться с Nullable?

Почему мы не можем использовать lateinit с переменными, допускающими значение NULL?

lateinit var v: String?

lateinit модификатор не разрешен для свойств типов, допускающих значение NULL

Я не знаю подробностей, но если подумать, если бы вы позволили это, зачем бы вы это сделали lateinit? Просто инициализируйте его как null.

Fred 29.05.2019 07:48

Послушай, я знаю, что инициализирую его некоторым значением, но это будет значение, допускающее значение NULL, при присвоении этого значения переменной, которую мы объявили, появится предупреждение

Abraham Mathew 29.05.2019 13:46
7
2
1 972
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

lateinit предназначен только для того, чтобы избежать проверок на null в будущем, поэтому модификатор lateinit не разрешен для свойств типов, допускающих значение null.

Если вы хотите, чтобы это было nullable, вы можете просто использовать лайк var b: String? = null

Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient.

For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In this case, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class.

To handle this case, you can mark the property with the lateinit modifier.

Вот почему он не поддерживает нулевой.

Итак, если вы укажете какой-либо вар как поздно, это означает, что компилятор просто игнорирует его для инициализации и помечает как ненулевой тип, который будет инициализирован в ближайшем будущем, и поэтому он не поддерживает тип, допускающий значение NULL, чтобы избежать неоднозначности во время выполнения.

Цитируйте документацию (и другие источники ответов), а не просто копируйте ее.

Alexey Romanov 29.05.2019 14:42

Kotlin's type system is aimed at eliminating the danger of null references from code

так что оба представляют собой компромиссы. С lateinit вы гарантируете, что переменная в конечном итоге будет инициализирована ненулевой. Если вы даже этого не можете гарантировать, вы можете использовать обнуляемый.

Если вы хотите создать переменную типа nullable, то вам не нужна поздняя инициализация. Док говорит

Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient. For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In this case, you cannot supply a nonnull initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class.

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

Одна из главных фич kotlin — Null Safe.

По умолчанию это не позволит вам создать нулевое значение. Вы явно определили
var a: String? = null
, Если вы не хотите инициализировать какое-либо значение переменной, приходит «lateinit». При использовании переменной lateinit вы предварительно проверяете, инициализирована она или нет.

Как указано в документации, lateinit специализируется на ненулевых свойствах:

Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient. For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In this case, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class.

Кроме того, если вы посмотрите на байтовый код такого свойства lateinit, вы увидите, что компилятор добавляет блок кода, чтобы гарантировать, что это свойство было инициализировано при доступе. Для свойств lateinitnull указывает на начальное, но недопустимое состояние свойств.

class WithLateInit {
    lateinit var something : String
}

становится

public final class WithLateInit {
   @NotNull
   public String something;

   @NotNull
   public final String getSomething() {
      String var10000 = this.something;
      if (var10000 == null) { // <- here you can see the lateinit check
         Intrinsics.throwUninitializedPropertyAccessException("something");
      }

      return var10000;
   }

  //setter
}

Другие вопросы по теме