Kotlin:相等比较似乎可以为空,但是大于比较不是 [英] Kotlin: equal comparison seems OK on nullable, but greater than comparison is not

查看:48
本文介绍了Kotlin:相等比较似乎可以为空,但是大于比较不是的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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'上是不允许的. 

这对我提出了两个问题:

  1. 为什么 == 2 可以正常工作,但是> = 2 不能正常工作?(我尝试了> 1 ,该错误与> = 2 相同.)
  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆