How to check if a “lateinit” variable has been initialized?

前端 未结 8 627
执念已碎
执念已碎 2020-11-29 15:37

I wonder if there is a way to check if a lateinit variable has been initialized. For example:

class Foo() {

    private lateinit var myFile: Fi         


        
相关标签:
8条回答
  • 2020-11-29 16:16
    kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized
    

    Bytecode says...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 creates an extra local variable of same instance and check if it null or not, if null then throws 'throwUninitializedPropertyAccessException' else return the local object. Above bytecode explained here Solution Since kotlin 1.2 it allows to check weather lateinit var has been initialized or not using .isInitialized

    0 讨论(0)
  • 2020-11-29 16:21

    You can easily do this by:

    ::variableName.isInitialized
    

    or

    this::variableName.isInitialized
    

    But if you are inside a listener or inner class, do this:

    this@YourClassName::variableName.isInitialized
    

    Note: The above statements work fine if you are writing them in the same file(same class or inner class) where the variable is declared but this will not work if you want to check the variable of other class (which could be superclass or any other class which is instantiated), for ex:

    class Test {
        lateinit var str:String
    }
    

    And to check if str is initialized:

    What we are doing here: checking isInitialized for field str of Test class in Test2 class. And we get an error backing field of var is not accessible at this point. Check a question already raised about this.

    0 讨论(0)
  • 2020-11-29 16:23

    Using .isInitialized property one can check initialization state of a lateinit variable.

    if(::file.isInitialized){
        //File is initialized
    }else{
        //File is not initialized
    }
    
    0 讨论(0)
  • 2020-11-29 16:31

    To check if a lateinit var were initialised or not use a .isInitialized on the reference to that property:

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

    This checking is only available for the properties that are accessible lexically, i.e. declared in the same type or in one of the outer types, or at top level in the same file.

    0 讨论(0)
  • 2020-11-29 16:34

    Try to use it and you will receive a UninitializedPropertyAccessException if it is not initialized.

    lateinit is specifically for cases where fields are initialized after construction, but before actual use (a model which most injection frameworks use). If this is not your use case lateinit might not be the right choice.

    EDIT: Based on what you want to do something like this would work better:

    val chosenFile = SimpleObjectProperty<File?>
    val button: Button
    
    // Disables the button if chosenFile.get() is null
    button.disableProperty.bind(chosenFile.isNull())
    
    0 讨论(0)
  • 2020-11-29 16:34

    Accepted answer gives me a compiler error in Kotlin 1.3+, I had to explicitly mention the this keyword before ::. Below is the working code.

    lateinit var file: File
    
    if (this::file.isInitialized) {
    
        // file is not null
    }
    
    0 讨论(0)
提交回复
热议问题