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