web-dev-qa-db-ja.com

"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)
}
226
Mathew Hany

Kotlin 1.2にはlateinitの改良があり、lateinit変数の初期化状態を直接チェックすることができます。

lateinit var file: File    

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

JetBrainsブログ または KEEPプロポーザル の発表を参照してください。

更新: Kotlin 1.2がリリースされました。 lateinitの機能強化はここにあります。

599
xsveda

それを使用しようとすると、初期化されていない場合はUninitializedPropertyAccessExceptionを受け取ります。

lateinitは特に、構築後で実際の使用前にフィールドが初期化される場合のためのものです(ほとんどのインジェクションフレームワークが使用するモデル)。これがあなたのユースケースではない場合、lateinitは正しい選択ではないかもしれません。

編集:このような何かをやりたいことに基づいてよりうまくいくでしょう:

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

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

.isInitializedプロパティを使用して、lateinit変数の初期化状態を確認できます。

if(::file.isInitialized){
    //File is initialized
}else{
    //File is not initialized
}
15
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'をスローし、そうでない場合はローカルオブジェクトを返します。上記のバイトコードの説明 here 解決策kotlin 1.2以降では、lateyinit varが初期化されているか、.isInitializedを使用していないかを確認できます。

0
takharsh

承認された回答Kotlin 1.3+でコンパイラエラーが発生します。::の前にthisキーワードを明示的に指定する必要がありました。以下は作業コードです。

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}
0

lateinit varが初期化されているかどうかを確認するには、そのプロパティへの参照に.isInitializedを使用します。

if (foo::bar.isInitialized) {
    println(foo.bar)
}

このチェックは、字句的にアクセス可能なプロパティ、つまり同じ型または外部型の1つで宣言されているプロパティ、または同じファイルの最上位レベルで宣言されているプロパティに対してのみ使用できます。

0
ARGeo