「lateinit」変数が初期化されているかどうかを確認するにはどうすればよいですか?


428

lateinit変数が初期化されているかどうかを確認する方法はあるのでしょうか。例えば:

class Foo() {

    private lateinit var myFile: File

    fun bar(path: String?) {
        path?.let { myFile = File(it) }
    }

    fun bar2() {
        myFile.whateverMethod()
        // May crash since I don't know whether myFile has been initialized
    }
}

3
たぶん、あなたが必要とするのは、プロパティをnull可能にして(型をに変更File?)、代わりにnullかどうかを確認することでしょうか?
MarcinKoziński、2016年

1
まあ、私は実際にしかし、私は編集する必要があります、それはトリックを行いますことをしようとしたallSeriesのVAR seriesDir?.listFiles()?.map { it.name }?.toTypedArray()非常に「きれい」ではありません、
マシュー・ハニー

1
プレーンな古いnullチェックを行うことができ、スマートキャストによりきれいになります。if (seriesDir != null) { allSeries = seriesDir.listFiles().map { it.name }.toTypedArray() }
MarcinKoziński、2016年

回答:


977

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

lateinit var file: File    

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

JetBrainsブログのアナウンスまたはKEEPプロポーザルを参照してください。

更新: Kotlin 1.2がリリースされました。lateinitここで拡張機能を見つけることができます:


3
@ fer.marino:まあ、Kotlin 1.2では実際lateinitにローカル変数にも使用できます。kotlinlang.org
docs /

9
this :: lateinitVar.isInitialized
vihkat

17
::以前の意味は何fileですか?
Malwinder Singh

5
@MalwinderSinghは、メンバー参照またはクラス参照を作成します。
notGeek

5
コトリンに恋して
Naveed Ahmad

46

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

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

これは質問に対する答えを提供しません。批評したり、著者に説明を要求するには、投稿の下にコメントを残してください。- 口コミより
gforce301

2
@ gforce301確認のために明確に使用されます。
Nikhil Katekhaye

39

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

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

編集:あなたがこのようなことをしたいことに基づいて、よりうまくいきます:

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

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

私はJavaFXアプリケーションを持っていて、変数(lateinit)が初期化されていない限り、常に無効になるボタンがあります。言い換えれば、変数が初期化されていない限り、ボタンを無効にしたいのです。それを行う良い方法はありますか?
Mathew Hany

@MathewHany正常に初期化されますか?プロパティゲッター/セッターと、ボタンの無効化されたプロパティにバインドできるSimpleBooleanPropertyを確認することをお勧めします
Kiskae

1
具体的には、4つのボタンを含むシンプルなアプリがあります。最初のボタンはDirectoryChooserダイアログを開き、他の3つは無効になります。ユーザーがディレクトリを選択すると、他のすべてのボタンがユーザーに使用可能になります。
Mathew Hany

@MathewHanyでは、SimpleObjectPropertyを使用して選択したファイルを保持し、isNullバインディングを使用して他のボタンを無効にすることをネイティブに実装できます。
Kiskae


19

これは次の方法で簡単に実行できます。

::variableName.isInitialized

または

this::variableName.isInitialized

ただし、リスナーまたは内部クラスの内部にいる場合は、次のようにします。

this@YourClassName::variableName.isInitialized

注:上記のステートメントは、変数が宣言されている同じファイル(同じクラスまたは内部クラス)にそれらを書き込んでいる場合は正常に機能しますが、他のクラス(スーパークラスではなく、またはで宣言されている)の変数をチェックする場合は機能しません別のファイル)、例:

class Test {
    lateinit var str:String
}

そして、strが初期化されているかどうかを確認するには:

ここに画像の説明を入力してください

ここでstrは、Testクラス内のTest2クラスのフィールドにアクセスしています。そして、この時点ではvarのエラーバッキングフィールドにアクセスできません。これについてすでに提起された質問を確認してください。


12

受け入れられた答えは私にコンパイラエラーを与えますKotlin 1.3+、私はthis前にキーワードを明示的に言及しなければなりません::でした。以下は作業コードです。

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}

このチェックを使用すると、未解決の参照のようなエラーが発生するローカル初期化変数を使用しています
MarGin

3

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

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

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


1
::以前の意味は何barですか?
Malwinder Singh

@Malwinder Singhが「メンバー参照またはクラス参照を作成する」-Kotlin Doc
DMonkey

0
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」をスローし、それ以外の場合はローカルオブジェクトを返します。ここでバイトコードの上で説明しました 解決策kotlin 1.2以降では、latelateinit varが初期化されているか、または使用されていないかを確認できます.isInitialized

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.