Scala中的==和.equals有什么区别?

在Scala中==.equals()什么区别,什么时候使用哪个?

这个实现和Java一样吗?

编辑:相关的问题谈论AnyVal具体情况。 更一般的情况是Any

你通常使用== ,它路由到equals ,除了它正确地对待null 。 参考平等(很less使用)是eq

==是最后的方法,并调用.equals ,这不是最终的。

这与Java完全不同,其中==是运算符而不是方法,严格地比较对象的引用相等性。

TL; DR

  • 重写equals方法来比较每个实例的内容。 这与Java中使用的equals方法相同
  • 使用==运算符进行比较,而不用担心null引用
  • 使用eq方法检查两个参数是否完全相同。 build议不要使用,除非你明白这是如何工作,往往equals将工作,而不是你所需要的。 并确保只使用AnyRef参数,不只是Any

注意:对于equals的情况,就像在Java中一样,如果切换参数,它可能不会返回相同的结果,例如1.equals(BigInt(1))将在返回false下返回false 。 这是因为每个实现只检查特定的types。 原始数字不检查是否第二个参数是NumberBigInttypes,但只有其他基本types

细节

AnyRef.equals(Any)方法是由子类重写的方法。 Java规范中的一个方法也来到了Scala。 如果在unboxed的实例上使用,可以调用它(尽pipe隐藏在Scala中;在int中使用int更为明显)。 默认实现只是比较引用(如在Java中)

Any.==(Any)方法比较两个对象,并允许两个参数为null(就像调用两个实例的静态方法一样)。 它比较两者是否为null ,然后调用盒装实例上的equals(Any)方法。

AnyRef.eq(AnyRef)方法比较引用,即实例在内存中的位置。 这个方法没有隐式装箱。

例子

  • 1 equals 2将返回false ,因为它redirect到Integer.equals(...)
  • 1 == 2将返回false ,因为它redirect到Integer.equals(...)
  • 1 eq 2不会编译,因为它需要两个参数都是AnyReftypes
  • new ArrayList() equals new ArrayList()将返回true ,因为它检查内容
  • new ArrayList() == new ArrayList()将返回true ,因为它redirect到equals(...)
  • new ArrayList() eq new ArrayList()将返回false ,因为两个参数都是不同的实例
  • foo equals foo将返回true ,除非foonull ,则会抛出NullPointerException
  • 即使foonullfoo == foo也会返回true
  • foo eq foo将返回true ,因为这两个参数链接到相同的引用

==equals FloatDoubletypes之间有一个有趣的区别:它们以不同的方式处理NaN

 scala> Double.NaN == Double.NaN res3: Boolean = false scala> Double.NaN equals Double.NaN res4: Boolean = true 

编辑:正如在评论中指出的 – “这也发生在Java中” – 取决于是什么:

 public static void main(final String... args) { final double unboxedNaN = Double.NaN; final Double boxedNaN = Double.valueOf(Double.NaN); System.out.println(unboxedNaN == unboxedNaN); System.out.println(boxedNaN == boxedNaN); System.out.println(boxedNaN.equals(boxedNaN)); } 

这将打印

 false true true 

因此, unboxedNanunboxedNan产生了false ,因为这是IEEE浮点数如何定义它,这实际上应该发生在每一种编程语言(虽然它以某种方式混淆身份的概念)。

盒装的NaN在Java中使用==比较真实,因为我们正在比较对象引用。

我没有一个解释的equals情况下,恕我直言,它确实应该performance为相同的==在unboxed double值,但它不。

由于Scala已经将原始types和对象types统一到Any ,并且根据需要将其翻译为原始双精度和双精度Double,所以翻译成Scala会稍微复杂一点。 因此,斯卡拉==显然归结为原始NaN值的比较,但是equals使用盒装Double值定义的那个(有很多隐式转换魔法正在进行,并且有些东西被RichDouble )。

如果你真的需要找出是否真的是NaN使用isNaN

  • Java: https : //docs.oracle.com/javase/7/docs/api/java/lang/Double.html#isNaN(double)
  • Scala: http : //www.scala-lang.org/files/archive/api/2.11.8/index.html#scala.Double@isNaN() : 布尔值

在Scala中==首先检查Null值,然后调用第一个对象的equals方法