问题
I have a lateinit var as
lateinit var someVariable: SomeVariable
I initialize this value like someVariable = SomeVariable()
and use it whenever I need.
At a certain point, I want to set everything to default and want to "uninitialize" someVariable
. How can I do that?
I am not looking for changing its type to a nullable
object and set null. I need to keep it a Non-Null
type.
回答1:
I don't think it's possible without some kind of wrapper (or reflection, but about in a moment).
In fact, lateinit is design for compatibility with DI frameworks etc. If you know that value can be uninitialized in any moment then you should use nullable
type.
So, what about that reflection thing? lateinit
is in fact a kind of smart wrapper that makes nullable
value to act like not nullable
, and instead of throwing NullPointerException
to throw UninitializedPropertyAccessException
. lateinit
property at the moment of declaration in JVM is null
, so, let's make it null
again ;)
So...
class MyClass {
lateinit var lateinitObject: Any
fun test() {
println("Is initialized: ${::lateinitObject.isInitialized}") // false
lateinitObject = Unit
println("Is initialized: ${::lateinitObject.isInitialized}") // true
resetField(this, "lateinitObject")
println("Is initialized: ${::lateinitObject.isInitialized}") // false
lateinitObject // this will throw UninitializedPropertyAccessException
}
}
fun resetField(target: Any, fieldName: String) {
val field = target.javaClass.getDeclaredField(fieldName)
with (field) {
isAccessible = true
set(target, null)
}
}
fun main() {
MyClass().test()
}
So, setting that field to null (and it's possible only via reflection) makes this filed uninitialized again. And one important thing - treat it as a curiosity, not like thing that should be in your production code.
来源:https://stackoverflow.com/questions/58335188/how-to-uninitialize-lateinit-in-kotlin