How to check if a “lateinit” variable has been ini

2019-01-16 11:18发布

问题:

I wonder if there is a way to check if a lateinit variable has been initialized.

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:

Try to use it and you will receive a UninitializedPropertyAccessException if it is not initialized.

lateinit is specifically for cases where fields are initialized after construction, but before actual use (a model which most injection frameworks use). If this is not your usecase lateinit might not be the right choice.

EDIT: Based on what you want to do something like this would work better:

val chosenFile = SimpleObjectProperty<File?>
val button: Button

// Disables the button if chosenFile.get() is null
button.disableProperty.bind(chosenFile.isNull())


回答2:

There is a lateinit improvement in Kotlin 1.2 that allows to check the initialization state of lateinit variable directly:

lateinit var file: File    

if (::file.isInitialized) { ... }

See the annoucement on JetBrains blog or the KEEP proposal.

UPDATE: Kotlin 1.2 has been released. You can find lateinit enhancements here:

  • Checking whether a lateinit var is initialized
  • Lateinit top-level properties and local variables


回答3:

Using .isInitialized property one can check initialization state of a lateinit variable.

if(::file.isInitialized){
    //File is initialized
}else{
    //File is not initialized
}


标签: kotlin