怎么避免!!在一个返回非可空的函数中

时间:2018-06-05 15:57:25

标签: kotlin nullable

在下面的示例中,函数应返回非空数据。 由于数据可以在流程中更改,因此需要为var,并且只能以可以为空为止。

我无法使用lateinit,因为if (d == null)的第一次调用将会抛出。

在该过程之后,它将被分配一个非空数据,但返回必须使用!!(双重或非空断言运算符)。

避免!!的最佳方法是什么?

fun testGetLowest (dataArray: List<Data>) : Data {
   var d: Data? = null
   for (i in dataArray.indecs) {

       if (d == null) {// first run
           d = dataArray[i]
       } else if {
           d.level < dataArray[i].level
           d = dataArray[i]
       }
    }
    return d!!
}

5 个答案:

答案 0 :(得分:2)

如果您不喜欢!!,请为其提供默认值。您将意识到,如果列表不为空,您只能提供默认值,但正如您所说,已知列表非空。这个故事的好处是类型系统没有跟踪列表大小,所以当你说dataArray[0]时,它会接受你的话。

fun testGetLowest(dataArray: List<Data>) : Data {
    var d: Data = dataArray[0]
    for (i in 1 until dataArray.size) {
        if (d.level < dataArray[i].level) {
            d = dataArray[i]
        }
    }
    return d
}

答案 1 :(得分:1)

即使你要将它转换为Option,当dataArray为空时你仍然需要处理这种情况,因此返回的值是未定义的。

如果你想让它成为一个完整的函数而不是抛出异常,你可以返回Option<Data>而不是Data,这样空dataArray的情况就会返回一个None并将其留给来电者来处理如何处理悲伤的道路。

答案 2 :(得分:1)

通常,您可以而且应该依靠编译器来推断可空性。这并不总是可行的,并且在设计的示例中,如果内循环运行但是d非空。如果dataArray至少有一个成员,则可以保证这一点。

使用这些知识,您可以使用require稍微重构代码来检查参数(对于至少一个数组成员)和checkNotNull来声明dataArray的状态为一个后置条件。

fun testGetLowest (dataArray: List<Data>) : Data {
   require(dataArray.size > 0, { "Expected dataArray to have size of at least 1: $dataArray")
   var d: Data? = null
   for (i in dataArray.indecs) {

       if (d == null) {// first run
           d = dataArray[i]
       } else if {
           d.level < dataArray[i].level
           d = dataArray[i]
       }
    }
    return checkNotNull(d, { "Expected d to be non-null through dataArray having at least one element and d being assigned in first iteration of loop" })
}

请记住,您可以返回checkNotNull(及类似运算符)的结果:

val checkedD = checkNotNull(d)

请参阅Google Guava的Preconditions,了解相似内容。

答案 3 :(得分:0)

如何进行相同检查,并覆盖空案例

fun testGetLowest(dataArray: List<Data>) 
    = dataArray.minBy { it.level } ?: throw AssertionError("List was empty")

这使用?:运算符来获取最小值,或者如果最小值为null(列表为空)则抛出错误。

答案 4 :(得分:0)

接受的答案完全没问题,只是提到了另一种通过更改代码中的一行来解决问题的方法:return d ?: dataArray[0]