Kotlin:相等比较似乎可以为空,但是大于比较不是 [英] Kotlin: equal comparison seems OK on nullable, but greater than comparison is not
问题描述
我是Kotlin的新手.我遵循的教程中,GUI部分涉及以下代码片段:
sampleList.addMouseListener(object:MouseAdapter(){重写fun mouseClicked(mouseEvent:MouseEvent?){如果(mouseEvent?.clickCount == 2){launchSelectedSample()}}})
mouseEvent
很明显为空.在以前的编码经验中,我习惯于将 mouseEvent?.clickCount == 2
这样的行更改为 mouseEvent?.clickCount>1
(或者也许> = 2
),以确保没有极端情况,其中点击发生得如此之快,以至于它从1跳到3.类似的东西.
因此,我将此代码切换为:
sampleList.addMouseListener(object:MouseAdapter(){重写fun mouseClicked(mouseEvent:MouseEvent?){如果(mouseEvent?.clickCount> = 2){launchSelectedSample()}}})
进行切换后(将 == 2
更改为> = 2
),我收到了IntelliJ的以下错误消息:>
操作员调用对应于点限定的调用'mouseEvent?.clickCount.compareTo(2)',该调用在可为空的接收器'mouseEvent?.clickCount'上是不允许的.
这对我提出了两个问题:
- 为什么
== 2
可以正常工作,但是> = 2
不能正常工作?(我尝试了> 1
,该错误与> = 2
相同.) - 处理拐角情况的正确方法是什么,我真正想要的是大于1的东西?
我喜欢确保 null
在运行时不会出错的想法,但我还是希望Kotlin完全摆脱 null
值并采取一些措施像Rust或Haskell.(不过,我确实很喜欢到目前为止对Kotlin的了解.)
如您所见,Kotlin的相等运算符( ==
和!=
)可以处理空值,而订单比较运算符(<
,< =
,>
,> =
)可以
这可能是因为很明显,什么相等检查应该均值检查null —两个null显然相等,并且非null值永远不应该等于null-尽管它根本不清楚应该意味着订单比较.(如果null不小于0,是否意味着null> = 0?否则,您不再具有定义明确的顺序.)
这反映在实现中: Any
有一个 equals()
方法,指示可以检查所有对象的相等性.(科特林(Kotlin)的文档明确指出了这一点,用于基础 Java方法,即非null对象绝不能等于null.)而Kotlin对 ==
和!=
运算符的实现显式检查是否为null.( a == b
转换为您必须用Java拼写的内容: a == null?b == null:a.equals(b)
.)>
但是订单比较的处理方式有所不同.它使用 Comparable
接口:只有具有自然顺序"的类型才能实现该功能;那些没有的,就无法以这种方式进行比较.由于null无法实现任何接口,因此它不能具有自然顺序,并且编译器会阻止您尝试比较.(Kotlin的文档并没有明确说明,因为该参数是不可为null的;但是用于底层Java接口的 解决方案
As you've found, Kotlin's equality operators (==
and !=
) can handle nulls, while the order comparison operators (<
, <=
, >
, >=
) can't.
This is probably because it's obvious what equality checks should mean for nulls — two nulls are clearly equal, and a non-null value should never equal a null — while it's not at all clear what it should mean for order comparisons. (If null isn't < 0, does that mean null >= 0? If not, you no longer have a well-defined ordering.)
This is reflected in the implementation: Any
has an equals()
method, indicating that all objects can be checked for equality. (Kotlin's documentation makes it explicit, as does that for the underlying Java method, that non-null objects must never equal null.) And Kotlin's implementation of the ==
and !=
operators explicitly checks for nulls. (a == b
translates to what you have to spell out in Java: a == null ? b == null : a.equals(b)
.)
But order comparison is handled differently. It uses the Comparable
interface: only types with a ‘natural ordering’ implement that; those that don't, can't be compared in that way. Since null can't implement any interfaces, it can't have a natural ordering, and the compiler prevents you trying the comparison. (Kotlin's documentation doesn't make this explicit, because the parameter is non-nullable; but that for the underlying Java interface says that such a comparison should return a NullPointerException.)
As to how you should handle this, the Elvis operator is probably the most concise solution:
if (mouseEvent?.clickCount ?: 0 >= 2)
If mouseEvent
is not null, this will get its clickCount
; otherwise, the safe-call ?.
will give the null directly, and then the ?:
will substitute 0. (That would also happen if the clickCount
held null, though that shouldn't be possible.) In every case, you end up with a non-nullable integer that can safely be compared with 2.
Of course, in practice, nothing should ever be calling a listener method and passing a null event. (I can't recall ever allowing for that back when I used to write Java Swing code for a living, or hitting any problems as a result.) So a simpler alternative might be declaring the parameter as non-nullable. But handling the null properly is just that little bit safer; and in this case, it doesn't add much extra code. So it's up to you!
这篇关于Kotlin:相等比较似乎可以为空,但是大于比较不是的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!