我是Kotlin的新手。我遵循的教程中,GUI部分涉及以下代码片段:
sampleList.addMouseListener(object: MouseAdapter() {
override fun mouseClicked(mouseEvent: MouseEvent?) {
if (mouseEvent?.clickCount == 2) {
launchSelectedSample()
}
}
})
mouseEvent
显然是可空的。在以前的编码经验中,我习惯将mouseEvent?.clickCount == 2
更改为mouseEvent?.clickCount > 1
(或也许是>=2
),确保没有极端情况点击发生的速度如此之快,以至于从1跳到3或类似的次数。
因此,我将此代码切换为:
sampleList.addMouseListener(object: MouseAdapter() {
override fun mouseClicked(mouseEvent: MouseEvent?) {
if (mouseEvent?.clickCount >= 2) {
launchSelectedSample()
}
}
})
进行切换(将==2
更改为>=2
)后,我收到了IntelliJ的以下错误消息:
Operator call corresponds to a dot-qualified call 'mouseEvent?.clickCount.compareTo(2)' which is not allowed on a nullable receiver 'mouseEvent?.clickCount'.
这对我提出了两个问题:
==2
可以正常工作,但是>=2
却不能正常工作? (我尝试过>1
,该错误与>=2
相同。)我喜欢确保null
在运行时不会出错的想法,但是我有点希望Kotlin是否完全摆脱了null
值,并做了Rust或Haskell之类的事情。 (不过,我确实很喜欢到目前为止对Kotlin的了解。)
答案 0 :(得分:3)
如您所见,Kotlin的相等运算符(==
和!=
)可以处理空值,而顺序比较运算符(<
,<=
,{{1 }},>
)。
这可能是因为很明显,什么相等检查应该均值检查空值-两个空值显然相等,并且一个非空值永远不应该等于空值-尽管根本不清楚应该意味着订单比较。 (如果null不小于0,是否意味着null> = 0?否则,您将不再有明确定义的顺序。)
这反映在实现中:>=
有一个Any
方法,指示可以检查所有对象是否相等。 (Kotlin的documentation并未明确指出,但对于基础Java方法says而言,非null对象绝不能等于null。)还有Kotlin对equals()
和{{ 1}}运算符显式检查是否为空。 ({==
转换为您必须用Java拼写的内容:!=
。)
但是订单比较的处理方式有所不同。它使用a == b
接口:只有具有“自然顺序”的类型才能实现;那些没有的,就无法以这种方式进行比较。由于null无法实现任何接口,因此它不能具有自然顺序,并且编译器会阻止您尝试比较。 (同样,Kotlin的documentation对此并不明确,因为该参数不可为空;但是底层Java接口says的文档中,这样的比较应返回NullPointerException。)
关于如何处理此问题,猫王运算符可能是最简洁的解决方案:
a == null ? b == null : a.equals(b)
如果Comparable
不为null,它将得到其if (mouseEvent?.clickCount ?: 0 >= 2)
;否则,安全呼叫mouseEvent
将直接给出null,然后clickCount
将替换为0。(如果?.
保持为null,也不会发生这种情况,但这不应该是在每种情况下,您最终都会得到一个非空整数,可以安全地与2进行比较。
当然,在实践中,绝对不应调用侦听器方法并传递null事件。 (我不记得曾经写过Java Swing代码来谋生,或者遇到任何问题。)所以一个更简单的选择可能是将参数声明为不可为空。但是正确处理null只是稍微安全一点。在这种情况下,它不会添加太多额外的代码。因此,取决于您!
答案 1 :(得分:1)
当date enseamble
2009-08-02 0
2009-08-03 0
2009-08-04 0
2009-08-05 0
2009-08-06 -1
2009-08-07 1
发生时,您期望mouseEvent?.clickCount >= 2
发生什么行为?
您可以使用elvis(mouseEvent == null
)运算符将mouseEvent?.clickCount
转换为NotNull:
?:
在这种情况下,如果val clickCount = mouseEvent?.clickCount ?: 0
if (clickCount >= 2) {
launchSelectedSample()
}
为空,则mouseEvent?.clickCount
将为0
mouseEvent
之所以有效,是因为==2
被科特林(Kotlin)认为是mouseEvent?.clickCount
,而比较null
是正确的,与null == 2
不同
答案 2 :(得分:1)
更多的科特林风格可以是:
mouseEvent?.clickCount?.let{
if(it >= 2) {
launchSelectedSample()
}
}
更加实用的风格:
mouseEvent?.clickCount?.takeIf { it >= 2 }?.let { launchSelectedSample() }