Come verificare se una variabile "lateinit" è stata inizializzata?


428

Mi chiedo se c'è un modo per verificare se una lateinitvariabile è stata inizializzata. Per esempio:

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
Forse ciò di cui hai bisogno è rendere la proprietà nullable (cambia il tipo in File?) e controlla invece se è null?
Marcin Koziński,

1
Bene, in realtà l'ho provato e farà il trucco, tuttavia dovrò modificare il allSeriesvar in seriesDir?.listFiles()?.map { it.name }?.toTypedArray(), che non è molto "carino"
Mathew Hany,

1
Puoi fare un semplice controllo null e smart cast lo renderà più bello. if (seriesDir != null) { allSeries = seriesDir.listFiles().map { it.name }.toTypedArray() }
Marcin Koziński,

Ti preghiamo di considerare di accettare una risposta
misantropo del

Risposte:


978

C'è un lateinitmiglioramento in Kotlin 1.2 che consente di controllare direttamente lo stato di inizializzazione della lateinitvariabile:

lateinit var file: File    

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

Vedi l'annuncio sul blog JetBrains o la proposta KEEP .

AGGIORNAMENTO: Kotlin 1.2 è stato rilasciato. Puoi trovare i lateinitmiglioramenti qui:


3
@ fer.marino: Bene, Kotlin 1.2 in realtà ti permette di usare lateinitanche per variabili locali, vedi kotlinlang.org/docs/reference/…
xsveda,

9
this :: lateinitVar.isInitialized
vihkat,

17
che cosa significa ::prima file?
Malwinder Singh,

5
@MalwinderSingh crea un riferimento membro o un riferimento di classe.
NotGeek

5
Innamorato di Kotlin adesso
Naveed Ahmad,

46

Utilizzando la .isInitializedproprietà si può verificare lo stato di inizializzazione di una variabile lateinit.

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

Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti a un autore, lascia un commento sotto il suo post. - Dalla recensione
gforce301

2
@ gforce301 Verrà sicuramente utilizzato per il controllo.
Nikhil Katekhaye l'

39

Prova a usarlo e riceverai un UninitializedPropertyAccessExceptionse non è inizializzato.

lateinitè specifico per i casi in cui i campi vengono inizializzati dopo la costruzione, ma prima dell'uso effettivo (un modello utilizzato dalla maggior parte dei framework di iniezione). In caso contrario, il tuo caso d'uso lateinitpotrebbe non essere la scelta giusta.

EDIT: in base a ciò che vuoi fare qualcosa del genere funzionerebbe meglio:

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

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

Ho un'applicazione JavaFX e ho un pulsante che sarà sempre disabilitato a meno che non sia lateinitstata inizializzata una variabile (che è ). In altre parole: voglio che il pulsante sia disabilitato finché la variabile non è stata inizializzata. C'è un buon modo per farlo?
Mathew Hany,

@MathewHany Come verrebbe inizializzato normalmente? Potresti voler esaminare il getter / setter di proprietà e una proprietà SimpleBoolean che puoi associare alla proprietà disabilitata del pulsante
Kiskae,

1
Per essere più specifici, ho una semplice app che contiene 4 pulsanti, il primo pulsante aprirà una finestra di dialogo DirectoryChooser e gli altri 3 saranno disabilitati, quando l'utente sceglie una directory, tutti gli altri pulsanti saranno disponibili per l'utente.
Mathew Hany,

@MathewHany puoi implementarlo nativamente usando SimpleObjectProperty per contenere il file scelto, quindi usando l' isNullassociazione per disabilitare gli altri pulsanti.
Kiskae,

1
kotlinlang.org/docs/reference/… La risposta di xsveda è più aggiornata
Serge

19

Puoi farlo facilmente tramite:

::variableName.isInitialized

o

this::variableName.isInitialized

Ma se ti trovi in ​​un ascoltatore o in una classe interna, fai questo:

this@YourClassName::variableName.isInitialized

Nota: le istruzioni precedenti funzionano correttamente se le stai scrivendo nello stesso file (stessa classe o classe interna) in cui viene dichiarata la variabile ma ciò non funzionerà se desideri controllare la variabile di un'altra classe (non la superclasse o dichiarata in un altro file) , ad esempio:

class Test {
    lateinit var str:String
}

E per verificare se str è inizializzato:

inserisci qui la descrizione dell'immagine

Quello che stiamo facendo qui accedendo al campo strdi Testclasse in Test2classe. E otteniamo un errore che supporta il campo var non è accessibile a questo punto. Controlla una domanda già sollevata al riguardo.


12

La risposta accettata mi dà un errore del compilatore Kotlin 1.3+, prima dovevo menzionare esplicitamente la thisparola chiave ::. Di seguito è riportato il codice di lavoro.

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}

Sto usando una variabile init locale quando uso questo controllo che fornisce un errore come riferimento irrisolto
MarGin

3

Per verificare se a è lateinit varstato inizializzato o meno utilizzare a .isInitializedsul riferimento a quella proprietà:

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

Questo controllo è disponibile solo per le proprietà accessibili in modo lessicale, ovvero dichiarate nello stesso tipo o in uno dei tipi esterni o al livello superiore nello stesso file.


1
che cosa significa ::prima bar?
Malwinder Singh,

@Malwinder Singh "crea un riferimento membro o un riferimento di classe" - Kotlin Doc
DMonkey

0
kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized

Bytecode dice ... blah blah ..

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 crea una variabile locale aggiuntiva della stessa istanza e controlla se è nulla o no, se null quindi genera 'throwUninitializedPropertyAccessException' altrimenti restituisce l'oggetto locale. Il bytecode sopra spiegato qui Soluzione Dal momento che kotlin 1.2 consente di verificare che lateinit var sia stato inizializzato o non utilizzato.isInitialized

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.