Implementation of how Kotlin securely accesses lateinit variables

  • 2021-11-14 07:17:12
  • OfStack

At the beginning of Kotlin design, non-null variables were not allowed to be initialized during declaration. To solve this problem, Kotlin lateinit allows us to declare a variable first, and then initialize it at some time in the future of the program execution cycle, so that there will be no error when compiling and checking because the attribute variables are not initialized. Uninitialized causes the following exception:


kotlin.UninitializedPropertyAccessException: lateinit property mList has not been initialized

So on Kotlin 1.2 and later, we often use reflection-based API to quickly check whether the lateinit property has been initialized.


private lateinit var mList: MutableList<String>

fun main(args: Array<String>) {
  if (::mList.isInitialized) {
    mList.add("")
  }
}

But if we have an lateinit attribute in one class, and then try to check that it is initialized in another class, as follows:


class PreA{
  lateinit var mList: MutableList<String>
}

class PreB{
  val mPreA = PreA()
  fun print(){
    if (mPreA::mList.isInitialized){

    }
  }
}

Will report an error:

Kotlin: Backing field of 'var mList: MutableList < String > ' is not accessible at this point

Because of the limitation of this reflection API, of course inner class is allowed. Please refer to the official for specific design details

So if we have similar requirements, we can directly add a new method to the target class to check the lateinit attribute:


class PreA{
  lateinit var mList: MutableList<String>
  fun isListInitialised() = ::mList.isInitialized
}

class PreB{
  val mPreA = PreA()
  fun print(){
    if (mPreA.isListInitialised()){
      mPreA.mList.add("")
    }
  }
}

Of course, it is also possible to catch UninitializedPropertyAccessException exceptions

Reference: StackOverflow


Related articles: