Comment vérifier si une variable «lateinit» a été initialisée?

428

Je me demande s'il existe un moyen de vérifier si une lateinitvariable a été initialisée. Par exemple:

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
    }
}
Mathew Hany
la source
3
Peut-être que ce dont vous avez besoin est de rendre la propriété nullable (changer le type en File?) et de vérifier simplement si elle est nulle à la place?
Marcin Koziński
1
Eh bien, j'ai essayé et ça fera l'affaire, mais je devrai éditer le allSeriesvar seriesDir?.listFiles()?.map { it.name }?.toTypedArray(), ce qui n'est pas très "joli"
Mathew Hany
1
Vous pouvez faire une simple vérification nulle et la fonte intelligente la rendra plus jolie. if (seriesDir != null) { allSeries = seriesDir.listFiles().map { it.name }.toTypedArray() }
Marcin Koziński
Veuillez envisager d'accepter une réponse
misanthrope

Réponses:

978

Il y a une lateinitamélioration dans Kotlin 1.2 qui permet de vérifier lateinitdirectement l' état d'initialisation de la variable:

lateinit var file: File    

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

Voir l'annonce sur le blog JetBrains ou la proposition KEEP .

MISE À JOUR: Kotlin 1.2 est sorti. Vous pouvez trouver des lateinitaméliorations ici:

xsveda
la source
3
@ fer.marino: Eh bien, Kotlin 1.2 vous permet en fait d'utiliser lateinitaussi pour les variables locales, voir kotlinlang.org/docs/reference/…
xsveda
9
this :: lateinitVar.isInitialized
vihkat
17
que signifie ::avant file?
Malwinder Singh
5
@MalwinderSingh crée une référence de membre ou une référence de classe.
notGeek
5
Amoureux de kotlin maintenant
Naveed Ahmad
46

En utilisant la .isInitializedpropriété, on peut vérifier l'état d'initialisation d'une variable Lateinit.

if(::file.isInitialized){
    //File is initialized
}else{
    //File is not initialized
}
Nikhil Katekhaye
la source
Cela ne fournit pas de réponse à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous son article. - De l'avis
gforce301
2
@ gforce301 Il sera définitivement utilisé pour la vérification.
Nikhil Katekhaye
39

Essayez de l'utiliser et vous en recevrez un UninitializedPropertyAccessExceptions'il n'est pas initialisé.

lateinitest spécifiquement pour les cas où les champs sont initialisés après la construction, mais avant l'utilisation réelle (un modèle que la plupart des frameworks d'injection utilisent). Si ce n'est pas le cas, votre cas d'utilisation lateinitn'est peut-être pas le bon choix.

EDIT: Sur la base de ce que vous voulez faire, quelque chose comme ça fonctionnerait mieux:

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

// Disables the button if chosenFile.get() is null
button.disableProperty.bind(chosenFile.isNull())
Kiskae
la source
J'ai une application JavaFX, et j'ai un bouton qui sera toujours désactivé à moins qu'une variable (qui est lateinit) ait été initialisée. En d'autres termes: je veux que le bouton soit désactivé tant que la variable n'a pas été initialisée. Y a-t-il un bon moyen de le faire?
Mathew Hany
@MathewHany Comment serait-il initialisé normalement? Vous voudrez peut-être regarder les getter / setters de propriété et une propriété SimpleBoolean que vous pouvez lier à la propriété désactivée du bouton
Kiskae
1
Pour être plus précis, j'ai une application simple qui contient 4 boutons, le premier bouton ouvrira une boîte de dialogue DirectoryChooser et les 3 autres seront désactivés, lorsque l'utilisateur choisira un répertoire, tous les autres boutons seront disponibles pour l'utilisateur.
Mathew Hany
@MathewHany vous pouvez implémenter nativement cela en utilisant un SimpleObjectProperty pour contenir le fichier choisi, puis en utilisant la isNullliaison pour désactiver les autres boutons.
Kiskae
1
kotlinlang.org/docs/reference/… La réponse de xsveda est plus à jour
Serge
19

Vous pouvez facilement le faire en:

::variableName.isInitialized

ou

this::variableName.isInitialized

Mais si vous êtes à l'intérieur d'un écouteur ou d'une classe interne, procédez comme suit:

this@YourClassName::variableName.isInitialized

Remarque: Les instructions ci-dessus fonctionnent correctement si vous les écrivez dans le même fichier (même classe ou classe interne) où la variable est déclarée, mais cela ne fonctionnera pas si vous souhaitez vérifier la variable d'une autre classe (pas la superclasse ou déclarée dans un autre fichier) , par exemple:

class Test {
    lateinit var str:String
}

Et pour vérifier si str est initialisé:

entrez la description de l'image ici

Ce que nous faisons ici, l'accès au domaine strde Testclasse en Test2classe. Et nous obtenons un champ de sauvegarde d'erreur de var n'est pas accessible à ce stade. Consultez une question déjà posée à ce sujet.

Suraj Vaishnav
la source
12

La réponse acceptée me donne une erreur de compilation dans Kotlin 1.3+, j'ai dû mentionner explicitement le thismot - clé avant ::. Voici le code de travail.

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}
Sazzad Hissain Khan
la source
J'utilise une variable d'initialisation locale lorsque j'utilise cette vérification qui donne une erreur comme une référence non résolue
MarGin
3

Pour vérifier si un a lateinit varété initialisé ou non, utilisez un .isInitializedsur la référence à cette propriété:

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

Cette vérification n'est disponible que pour les propriétés accessibles lexicalement, c'est-à-dire déclarées dans le même type ou dans l'un des types externes, ou au niveau supérieur dans le même fichier.

Andy
la source
1
que signifie ::avant bar?
Malwinder Singh
@Malwinder Singh "crée une référence de membre ou une référence de classe" - Kotlin Doc
DMonkey
0
kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized

Bytecode dit ... bla bla ..

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 crée une variable locale supplémentaire de la même instance et vérifie si elle est nulle ou non, si null lance ensuite 'throwUninitializedPropertyAccessException' sinon retourne l'objet local. Ci-dessus le bytecode expliqué ici Solution Depuis kotlin 1.2, il permet de vérifier la météo tardive var a été initialisée ou ne pas utiliser.isInitialized

takharsh
la source