Почему поздний init var нельзя использовать с Nullable? - PullRequest
1 голос
/ 29 мая 2019

Почему мы не можем использовать lateinit с переменными Nullable?Модификатор

lateinit var v: String?

lateinit недопустим для свойств обнуляемых типов

Ответы [ 6 ]

3 голосов
/ 29 мая 2019

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

Обычно свойства, объявленные как имеющие ненулевой тип, должны быть инициализированы в конструкторе.Однако довольно часто это не удобно.Например, свойства могут быть инициализированы посредством внедрения зависимости или в методе настройки модульного теста.В этом случае вы не можете предоставить ненулевой инициализатор в конструкторе, но вы все равно хотите избегать нулевых проверок при обращении к свойству внутри тела класса.

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

3 голосов
/ 29 мая 2019

lateinit только для предотвращения нулевых проверок в будущем, поэтому модификатор lateinit недопустим для свойств обнуляемых типов.

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

2 голосов
/ 29 мая 2019

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

Обычно свойства, объявленные как имеющие ненулевой тип , должны быть инициализированы в конструкторе. Однако довольно часто это не удобно. Например, свойства могут быть инициализированы посредством внедрения зависимости или в методе настройки модульного теста. В этом случае вы не можете предоставить ненулевой инициализатор в конструкторе, но вы все равно хотите избегать нулевых проверок при ссылке на свойство внутри тела класса.

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

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
}
1 голос
/ 29 мая 2019

Система типов Kotlin нацелена на устранение опасности нулевых ссылок из кода

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

1 голос
/ 29 мая 2019

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

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

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

Именно поэтому оно не поддерживает null .

Таким образом, если вы укажете var как lateinit , означающее, что компилятор просто игнорирует его для инициализации и пометит его как ненулевой тип , который будет инициализирован в ближайшем будущем, иВот почему он не поддерживает обнуляемый тип, чтобы избежать двусмысленности во время выполнения.

0 голосов
/ 29 мая 2019

Одной из основных функций в kotlin является Null Safe.

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

...