Kotlin:检查lazy val是否已初始化

Kotlin:检查lazy val是否已初始化,kotlin,Kotlin,是否有一种方法可以判断是否在Kotlin中初始化了惰性val,而不必在过程中初始化它 例如,如果我有一个懒惰的val,查询它是否为null将实例化它 val messageBroker: MessageBroker by lazy { MessageBroker() } if (messageBroker == null) { // oops } 我可能会使用第二个变量,但这看起来很混乱 private var isMessageBrokerInstantiated: Boolean

是否有一种方法可以判断是否在Kotlin中初始化了惰性val,而不必在过程中初始化它

例如,如果我有一个懒惰的val,查询它是否为null将实例化它

val messageBroker: MessageBroker by lazy { MessageBroker() }
if (messageBroker == null) {
    // oops
}
我可能会使用第二个变量,但这看起来很混乱

private var isMessageBrokerInstantiated: Boolean = false
val messageBroker: MessageBroker by lazy {
    isMessageBrokerInstantiated = true
    MessageBroker()
}

...

if (!isMessageBrokerInstantiated) {
    // use case
}
是否有一些性感的方法来确定这一点,比如
if(Lazy(messageBroker).isinstated())


相关(但不相同):

有一种方法,但您必须访问由
lazy{}
返回的委托对象:

val messageBrokerDelegate = lazy { MessageBroker() }
val messageBroker by messageBrokerDelegate

if(messageBrokerDelegate.isInitialized())
    ...

isInitialized
是接口上的一个公共方法
Lazy
,以下是自Kotlin 1.1以来的。

,您可以使用直接访问属性委托

您可以为属性引用编写扩展属性,以检查它是否具有已初始化的
Lazy
委托:

/**
 * Returns true if a lazy property reference has been initialized, or if the property is not lazy.
 */
val KProperty0<*>.isLazyInitialized: Boolean
    get() {
        if (this !is Lazy<*>) return true

        // Prevent IllegalAccessException from JVM access check on private properties.
        val originalAccessLevel = isAccessible
        isAccessible = true
        val isLazyInitialized = (getDelegate() as Lazy<*>).isInitialized()
        // Reset access level.
        isAccessible = originalAccessLevel
        return isLazyInitialized
    }
此解决方案要求
kotlin reflect
位于类路径上。使用Gradle,使用编译“org.jetbrains.kotlin:kotlin reflect:$kotlin_version”


.getDelegate()
需要
isAccessible=true
部分,因为否则它无法访问存储委托引用的私有字段。

测试惰性属性是否足够简单:

import kotlin.reflect.KProperty0
import kotlin.reflect.jvm.isAccessible

val KProperty0<*>.isLazyInitialized: Boolean
    get() {
        // Prevent IllegalAccessException from JVM access check
        isAccessible = true
        return (getDelegate() as Lazy<*>).isInitialized()
    }
导入kotlin.reflect.KProperty0
导入kotlin.reflect.jvm.isAccessible
val KProperty0.isLazyInitialized:布尔值
得到(){
//从JVM访问检查中防止IllegalAccessException
isAccessible=true
return(getDelegate()为Lazy).isInitialized()
}
…但您可以更轻松地引用属性,而无需对其进行初始化:

/**
 * Returns the value of the given lazy property if initialized, null
 * otherwise.
 */
val <T> KProperty0<T>.orNull: T?
    get() = if (isLazyInitialized) get() else null
/**
*返回给定惰性属性的值(如果已初始化),null
*否则。
*/
val KProperty0.orNull:T?
get()=如果(isLazyInitialized)get()else为空
现在,您可以执行以下操作:

private val myList by lazy {
    mutableSetOf<String>()
}

fun add(str: String) {
    // Create the list if necessary
    myList += str
}

fun remove(str: String) {
    // Don't create the list
    ::myList.orNull?.remove(str)
}

fun clear() {
    // Don't create the list
    ::myList.orNull?.clear()
}
private val myList by lazy{
可变集合
}
趣味添加(str:String){
//如有必要,创建列表
myList+=str
}
乐趣移除(str:String){
//不要创建列表
::myList.orNull?删除(str)
}
趣味十足{
//不要创建列表
::myList.orNull?.clear()
}

注意,您也可以直接使用
惰性
而不是作为委托,并使用访问惰性计算值。也请参见。哇,我在发行说明中没有看到它!确保导入isAccessible:import kotlin.reflect.jvm.isAccessible我必须删除“if(this!is Lazy)return true”,否则它将正常工作。1.3中的更改?如果您使用的是R8(可能也是ProGuard,未经测试),那么缩小需要排除两件事:包含字段的类必须是可访问的,以及它的父类和实现的接口。字段本身必须标记为
@delegate:Keep
@Neikius Same。
private val myList by lazy {
    mutableSetOf<String>()
}

fun add(str: String) {
    // Create the list if necessary
    myList += str
}

fun remove(str: String) {
    // Don't create the list
    ::myList.orNull?.remove(str)
}

fun clear() {
    // Don't create the list
    ::myList.orNull?.clear()
}