Как проверить, была ли инициализирована переменная "lateinit"?
Интересно, есть ли способ проверить, была ли инициализирована переменная lateinit
.
import javafx.application.Application
import javafx.event.EventHandler
import javafx.geometry.Insets
import javafx.geometry.Pos
import javafx.scene.Scene
import javafx.scene.control.Button
import javafx.scene.control.ComboBox
import javafx.scene.layout.VBox
import javafx.stage.DirectoryChooser
import javafx.stage.Stage
import java.io.File
class SeriesManager() {
lateinit var seriesDir: File
val allSeries by lazy {
seriesDir.listFiles().map { it.name }.toTypedArray()
}
}
class SeriesManagerUI : Application() {
override fun start(primaryStage: Stage) {
val sm = SeriesManager()
val setSeriesDirBtn = Button("Change all series location").apply {
onAction = EventHandler {
sm.seriesDir = DirectoryChooser().apply {
title = "Choose all series location"
}.showDialog(primaryStage)
}
}
val allSeriesList = ComboBox<String>().apply {
promptText = "Select a series from here"
isDisable = // I want this to be always true, unless the SeriesManager.seriesDir has been initialized
}
val setCurrentEpisodeBtn = Button("Change the current episode")
val openNextEpisode = Button("Watch the next episode")
val layout = VBox(
setSeriesDirBtn,
allSeriesList,
setCurrentEpisodeBtn,
openNextEpisode
).apply {
padding = Insets(15.0)
spacing = 10.0
alignment = Pos.CENTER
}
primaryStage.apply {
scene = Scene(layout).apply {
minWidth = 300.0
isResizable = false
}
title = "Series Manager"
}.show()
}
}
fun main(args: Array<String>) {
Application.launch(SeriesManagerUI::class.java, *args)
}
Ответы
Ответ 1
В Kotlin 1.2 есть улучшение lateinit
, которое позволяет напрямую проверить состояние инициализации lateinit
:
lateinit var file: File
if (::file.isInitialized) { ... }
См. аннуляцию на блог JetBrains или предложение KEEP.
ОБНОВЛЕНИЕ: Вышел Kotlin 1.2. Вы можете найти улучшения lateinit
здесь:
Ответ 2
Попробуйте использовать его, и вы получите UninitializedPropertyAccessException
если оно не инициализировано.
lateinit
специально предназначен для случаев, когда поля инициализируются после построения, но перед фактическим использованием (модель, которую использует большинство сред внедрения). Если это не ваш вариант использования, то lateinit
может быть неправильным выбором.
РЕДАКТИРОВАТЬ: Исходя из того, что вы хотите сделать, что-то вроде этого будет работать лучше:
val chosenFile = SimpleObjectProperty<File?>
val button: Button
// Disables the button if chosenFile.get() is null
button.disableProperty.bind(chosenFile.isNull())
Ответ 3
Используя свойство .isInitialized
можно проверить состояние инициализации переменной lateinit.
if(::file.isInitialized){
//File is initialized
}else{
//File is not initialized
}
Ответ 4
Чтобы проверить, были ли инициализированы lateinit var
или нет, используйте .isInitialized
для ссылки на это свойство:
if (foo::bar.isInitialized) {
println(foo.bar)
}
Эта проверка доступна только для свойств, которые доступны лексически, то есть объявлены в том же типе или в одном из внешних типов, или на верхнем уровне в том же файле.
Ответ 5
kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized
Байт-код говорит... бла-бла..
public final static synthetic access$getClientKeypair$p(Lcom/takharsh/ecdh/MainActivity;)Ljava/security/KeyPair;
'L0
LINENUMBER 11 L0
ALOAD 0
GETFIELD com/takharsh/ecdh/MainActivity.clientKeypair : Ljava/security/KeyPair;
DUP
IFNONNULL L1
LDC "clientKeypair"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.throwUninitializedPropertyAccessException (Ljava/lang/String;)V
L1
ARETURN
L2 LOCALVARIABLE $ this Lcom/takharsh/ecdh/MainActivity; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 1
Kotlin создает дополнительную локальную переменную того же экземпляра и проверяет, имеет ли она значение NULL или нет, если NULL, то генерирует исключение throwUninitializedPropertyAccessException, иначе возвращает локальный объект. Над байткодом объяснено здесь решение Поскольку Котлин 1.2 позволяет проверить погоду lateinit вар инициализирован или неиспользования .isInitialized
Ответ 6
Принятый ответ дает мне ошибку компилятора в Kotlin 1.3+
, мне пришлось явно упомянуть ключевое слово this
перед ::
. Ниже приведен рабочий код.
lateinit var file: File
if (this::file.isInitialized) {
// file is not null
}