当前位置: 首页 > 知识库问答 >
问题:

如何处理未初始化的lateinit变量

阎辰钊
2023-03-14

我正在将一个项目从java迁移到kotlin,该项目使用了许多可能为空的变量,并且在与用户或外部作业进行一些交互之前不会初始化它们。

我试图使用kotlin null安全优势,并且我试图避免在源代码中使用<code>nulllateinitvar location:location?=空

我这样做是为了避免使用< code >?每次我需要使用这些变量时。现在的问题是...如果变量没有初始化会发生什么?

例如,如果我需要在代码的某个部分调用location.getX()会发生什么?如何处理位置仍未初始化的情况?

我想用这个来处理它:

if (!this::location.isInitialized){
    location.getX()
}

但是,然后,我用初始化等的样板代码填充代码...所以。。。最后,我预付了没有空安全性的项目的旧java版本,它更清晰,更短。

如果我回到< code>var location: Location?= null,那么,我需要使用

location.let {
    it.getX()
}

location?.getX()

在第二种情况下,我仍然在处理null,这是我试图避免的事情

是不是我做错了什么?我必须返回空变量和变量位置:位置?=null而不是使用lateinit?有没有更好的方法

共有3个答案

狄旻
2023-03-14

你可以简化x?. let{}

改变:

location.let {
    it.getX()
}

至:

location?.getX()

并设置如下默认值:

val x = location?.getX() ?: 0
贝浩歌
2023-03-14

lateinit只能用于保证变量被初始化的情况,只是不可能在编译时验证这种保证。一个很好的例子是Activity.onCreate:虽然静态编程语言编译器无法知道在onCreate中初始化的字段在onResume中保证不为空,但它在Android SDK中是一个非常强大的契约,因此对该字段使用lateinit并避免空检查是合理的。

对于任何在访问时不能保证为非空的东西,坚持使用可空类型,像往常一样进行空检查。对于任何保证为非空的内容,使用< code>lateinit而不进行任何额外的检查:如果这些调用点导致崩溃,则移除< code>lateinit并将类型更改为nullable。

桂坚
2023-03-14

我认为您对如何在静态编程语言中使用null有一个错误的概念。正是由于Kotlin的null安全特性,您可以安全地使属性为null。如果某些东西不能始终可用,它应该为null。您正在滥用lateinit,通过强制您记住检查属性是否已初始化来使您的属性不安全,就像您总是必须记住检查Java中的字段是否为null一样。因此,您重新引入了静态编程语言null安全解决的相同问题。

如果某些东西有时不可用,将其设置为null是非常合适的。Kotlin的空安全功能将确保您不会忘记检查这种可能的状态。

更多阅读,来自Kotlin设计负责人:Null是你的朋友

延迟应仅由在 onCreate() 之后永远不会为空的属性使用。

——

也许你问的是如何更简洁地检查位置上的null,而不必处理其内部属性仍然为null?除了<代码>?。let模式,您可以使用这个:

val location = location ?: return

// you can now freely use non-null location in this function
// from the local reference known to be non-null

?。letcase与Java中的<code>if(x!=null)

location?.let { location ->
    // freely use location.getX() and getY() inside the braces
}

在这两种模式之间,您总是拥有与Java检查方式一样简洁的代码

 类似资料: