Question or issue of Kotlin Programming:
I wonder if there is a way to check if a lateinit variable has been initialized. For example:
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 } }
How to solve this issue?
Solution no. 1:
There is a lateinit
improvement in Kotlin 1.2 that allows to check the initialization state of lateinit
variable directly:
lateinit var file: File if (this::file.isInitialized) { ... }
See the annoucement on JetBrains blog or the KEEP proposal.
UPDATE: Kotlin 1.2 has been released. You can find lateinit
enhancements here:
- Checking whether a lateinit var is initialized
- Lateinit top-level properties and local variables
Solution no. 2:
Using .isInitialized
property one can check initialization state of a lateinit variable.
if (::file.isInitialized) { // File is initialized } else { // File is not initialized }
Solution no. 3:
You can easily do this by:
::variableName.isInitialized
or
this::variableName.isInitialized
But if you are inside a listener or inner class, do this:
[email protected]::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 a 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.
Solution no. 4:
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 val button: Button // Disables the button if chosenFile.get() is null button.disableProperty.bind(chosenFile.isNull())
Solution no. 5:
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 }
Solution no. 6:
If you have a lateinit
property in one class and need to check if it is initialized from another class
if(foo::file.isInitialized) // this wouldn't work
The workaround I have found is to create a function to check if the property is initialized and then you can call that function from any other class.
Example:
class Foo() { private lateinit var myFile: File fun isFileInitialised() = ::file.isInitialized } // in another class class Bar() { val foo = Foo() if(foo.isFileInitialised()) // this should work }
Solution no. 7:
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.
Solution no. 8:
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