在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/

    10-11 14:32