Подтвердить что ты не робот

Как проверить, была ли инициализирована переменная "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)
}
4b9b3361

Ответ 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
}