绑定&x27;lateinit';Kotlin中带条件的修饰符

绑定&x27;lateinit';Kotlin中带条件的修饰符,kotlin,Kotlin,在Kotlin中,我们对惰性变量初始化使用了lateinit修饰符,而不是var something:something?=空 在我的情况下,我有一个元素的列表,当我有第一个对象时,我想将它分配给lateinit变量。 因此,我尝试了几种方法来实现这一点 首先,使用“firstOrNull()”方法 第一个解决方案失败,因为applicationHolder不接受可为空的applicationHolder类型。(类型推断失败。预期类型不匹配:推断类型为ApplicationHolder?但预期为

在Kotlin中,我们对惰性变量初始化使用了
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()