在Kotlin中,我们使用lateinit
修饰符代替了var something: Something? = null
来进行延迟变量初始化。
在我的情况下,我有一个Element
的列表,当我拥有第一个对象时,我想将其分配给lateinit
变量。
因此,我尝试了几种方法来实现这一目标。
使用``firstOrNull()''方法的第一个
lateinit var applicationHolder: ApplicationHolder
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()
第一个解决方案失败,因为
applicationHolder
不接受ApplicationHolder的Nullable类型。 (类型推断失败。预期的类型不匹配:推断的类型为ApplicationHolder ?,但应为ApplicationHolder。)尽管我可以使用
first
而不是firstOrNull
来实现此目的,但它太危险了,因为列表可以为空。第二个,使用if-condition
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修饰符)
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()
第三个解决方案已成功编译并运行良好。
简而言之,我的问题如下。
最佳答案
为什么在这里对可空类型使用lateinit?
这给我敲响了警钟:
如果您尝试访问Lateinit对象而不对其进行初始化,则应用程序将崩溃。如果一定要初始化,则应使用Lateinit。
我会将代码更改为您避免使用的代码:var something: Something? = null
然后使用firstOrNull()方法。 kotlin null安全类型系统将强制您处理null,从而获得安全代码!
关于kotlin - 在Kotlin中将 'lateinit'修饰符与条件绑定(bind),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54995388/