当Kotlin函数不采用可空类型时,正确的方法是什么?

所以我正在解决Koans问题,通过我的过于复杂的解决方案碰到一个困扰我的东西。 我在可空类型上使用Int.compareTo()函数。 如果第一个是可空的,这是“容易的”,因为我只写:

val a : Int? = 1 val b : Int = 1 a?.compareTo(b) 

但是,如果b是可以空的,那么我不能使它工作,也许我错过了什么地方? 那么在这种情况下该怎么办?

 val a : Int? = 1 val b : Int? = 2 a?.compareTo(b) 

我得到一个语法错误说:“下面的函数都不能用提供的参数调用。

但是,当我介绍这个:

 val a : Int? = 1 val b : Int? = 2 val x : Int = b ?: 0; o1?.compareTo(x) 

它的作品,但它感觉不是这样做的正确方法。 有没有更好的办法?

你可以做

 val a: Int? = 1 val b: Int? = 2 b?.let { a?.compareTo(b) } 

只有在b不为空的情况下,才会执行块。

要不就

 if (a != null && b != null) { a.compareTo(b) } 

我认为第二个解决方案非常清晰,易于阅读。

Int.compareTo()方法的签名没有为可为空的参数定义,所以不可能在没有确保参数的null安全性的情况下通过例如使用一个elvis操作符来完成,就像你所建议的一样。

你应该尝试实现你的解决方案,而不是可空的。 但是,如果你仍然需要它,如果可以安全地假设null==0你不应该使用?. 方法调用。 它会返回给你一个Int? 以及。 只需将两个null整数映射到0。

 (a?:0).compareTo(b?:0) 

唯一更好的方法是实现compareTo自己。 默认的比较不知道你想要比较什么结果,即12nullnullnull 。 它只知道如何比较实际的数字。 我认为你最好的方法是实现你想要处理null的行为。

示例实现:

 fun main(args: Array<String>) { println(compareNullableInts(null, 2)) // -1 println(compareNullableInts(null, null)) // 0 println(compareNullableInts(2, null)) // 1 println(compareNullableInts(10, 5)) // 1 } fun compareNullableInts(a: Int?, b: Int?): Int { if (a == null && b == null) return 0 if (a == null) return -1 if (b == null) return 1 return a.compareTo(b) } 

表达应该是这样的:

 val result = b?.let { a?.compareTo(b) ?: -1 } ?: 1; 

例子

 > a = 1 b = 2 ---> -1 > a = null b = 2 ---> -1 > a = null b = -1 ---> -1 > a = 1 b = null ---> 1 > a = -1 b = null ---> 1 > a = null b = null ---> 1 // the order is no matter 

如果你想让null比较null返回0那么表达式有点长:

 val result = b?.let { a?.compareTo(b) ?: -1 } ?: a?.let { 1 } ?: 0; 

注意 :你不关心性能,因为let函数是一个内联函数。 这意味着它将在java中生成如下所示的代码:

 int result = b != null ? a != null ? a.compareTo(b) : -1 : a != null ? 1 : 0;