绑定&x27;lateinit';Kotlin中带条件的修饰符
在Kotlin中,我们对惰性变量初始化使用了绑定&x27;lateinit';Kotlin中带条件的修饰符,kotlin,Kotlin,在Kotlin中,我们对惰性变量初始化使用了lateinit修饰符,而不是var something:something?=空 在我的情况下,我有一个元素的列表,当我有第一个对象时,我想将它分配给lateinit变量。 因此,我尝试了几种方法来实现这一点 首先,使用“firstOrNull()”方法 第一个解决方案失败,因为applicationHolder不接受可为空的applicationHolder类型。(类型推断失败。预期类型不匹配:推断类型为ApplicationHolder?但预期为
lateinit
修饰符,而不是var something:something?=空
在我的情况下,我有一个元素的列表
,当我有第一个对象时,我想将它分配给lateinit
变量。
因此,我尝试了几种方法来实现这一点
首先,使用“firstOrNull()”方法
第一个解决方案失败,因为applicationHolder
不接受可为空的applicationHolder类型。(类型推断失败。预期类型不匹配:推断类型为ApplicationHolder?但预期为ApplicationHolder。)
虽然我可以使用first
而不是firstOrNull
来实现这一点,但这太危险了,因为列表可能是空的
秒,使用if条件
val item = env.getElementsAnnotatedWith(InjectApplication::class.java)
.map {
ApplicationHolder(it, (it as TypeElement).asClassName(), it.simpleName.toString()).apply {
val component = it.getAnnotation(InjectApplication::class.java).getComponent()
componentClass = component
}
}.firstOrNull()
if (item != null) {
applicationHolder = item
}
第二个解决方案成功编译并运行良好
第三个,使用支持属性(实际上,此解决方案不使用lateinit修饰符)
第三个解决方案成功编译并运行良好
简言之,我的问题如下
为什么在这里对可为null的类型使用lateinit 这给我敲响了警钟: 这太危险了,因为列表可能是空的 如果尝试访问lateinit对象而不初始化它,则应用程序将崩溃。如果肯定要初始化,则应使用Lateinit 我会将代码更改为您避免的代码:
var something:something?=空
然后使用firstOrNull()方法。kotlin null安全类型系统将强制您处理null,从而生成安全代码 可以通过调用this::applicationHolder.isInitialized
(这在Kotlin 1.2;info中引入)来检查是否已初始化lateinit
但是,根据@user8159708的回答,它仍然有点异味。重新处理使属性为null会使访问变得稍微困难一些,但安全得多。如果列表为空,您希望保持applicationHolder未初始化还是希望抛出异常?因为该部分是库代码,我认为与其抛出一个异常,还不如不初始化它。然后你应该使用第二个变量,因为如果列表为空,这将使变量保持未初始化状态。如果要添加
?:将NullPointerException(“未初始化”)
抛出到第一个变量,而不是编译,它将等效于第三个变量(当列表为空时,两者都会抛出异常)。我不知道你会如何改进它。谢谢你的回答,我会根据目的考虑更多。正如你所说,在这种情况下使用lateinit(如果变量可以为null)是不合适的。因此,我将applicationHolder
更改为可空变量,并在尝试使用此变量时实现检查逻辑。谢谢你的明确回答!
val item = env.getElementsAnnotatedWith(InjectApplication::class.java)
.map {
ApplicationHolder(it, (it as TypeElement).asClassName(), it.simpleName.toString()).apply {
val component = it.getAnnotation(InjectApplication::class.java).getComponent()
componentClass = component
}
}.firstOrNull()
if (item != null) {
applicationHolder = item
}
val applicationHolder: ApplicationHolder
get() {
return _applicationHolder ?: throw NullPointerException("Not initialized")
}
private var _applicationHolder: ApplicationHolder? = null
_applicationHolder = env.getElementsAnnotatedWith(InjectApplication::class.java)
.map {
ApplicationHolder(it, (it as TypeElement).asClassName(), it.simpleName.toString()).apply {
val component = it.getAnnotation(InjectApplication::class.java).getComponent()
componentClass = component
}
}.firstOrNull()