Scala中`null == last`和`null eq last`之间有什么区别?

Fre*_*ind 7 scala equals

我在MessageQueue.scalascala 2.7.7 的内置类中看到,在第164行附近,它是:

def extractFirst(p: Any => Boolean): MessageQueueElement = {
changeSize(-1) // assume size decreases by 1

val msg = if (null eq last) null
else {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我不太了解val msg = if (null eq last) null,为什么使用eq,但不是null.如果我写if (last==null) null,是否正确?有什么区别吗?

小智 13

== is的 任一侧null 或者第一个操作数的== 计算结果为 null时,Scala将不会调用equals.所以,在这种情况下,是的,x == null是一样的x eq null; 该equals方法未被调用.请注意以下情况.

考虑一下:

class X {
   // this is just for testing
   // any equals that returns true when the other object is null
   // is arguably broken. thus even though it may be invoked
   // the end semantics should remain the same
   override def equals(x: Any) = true
}
var x = new X()
x == null // false -- compiler optimization?
null == x // false
var y = null
y == x // false -- see documentation below, y is null, x is not
x == y // true  -- x does not evaluate to null, equals invokes
x eq y // false
Run Code Online (Sandbox Code Playgroud)

请注意:

(new X()) == null
Run Code Online (Sandbox Code Playgroud)

导致警告说"新鲜物体"永远不会相等(为空).

我怀疑有可能是发出稍微/不同的代码x == yx == null(如果等号必须调用),但还没有检查.

快乐的编码.


Scala语言规范的第6.3节(空值)有这样的说法:

null值的类型为scala.Null,因此与每个引用类型兼容.它表示引用特殊"空"对象的引用值.此对象在类scala.AnyRef中实现方法,如下所示:

  • [null] eq(x)和[null] ==(x)如果参数x也是"null"对象,则返回true.
  • ne(x)和!=(x)如果参数x不是"null"对象,则返回true.
  • isInstanceOf [T]始终返回false.
  • 如果T符合scala.AnyRef,则asInstanceOf [T]返回"null"对象,否则抛出NullPointerException.

对"null"对象的任何其他成员的引用会导致抛出NullPointerException.