159

==Scala 中的和之间有什么区别,什么.equals()时候使用哪个?

实现与Java中的相同吗?

编辑:相关问题讨论了AnyVal. 更一般的情况是Any

4

5 回答 5

213

您通常使用==, 它路由到equals,除了它null正确对待 s 。引用相等(很少使用)是eq.

于 2011-10-06T22:33:15.547 回答
38

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

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

于 2011-10-06T23:10:34.340 回答
38

TL;博士

  • 覆盖equals方法来比较每个实例的内容。这与equalsJava 中使用的方法相同
  • 使用==运算符进行比较,无需担心null引用
  • 使用eq方法检查两个参数是否完全相同。建议不要使用,除非您了解它是如何工作的,并且通常equals会为您需要的东西工作。并确保仅将其与AnyRef参数一起使用,而不仅仅是Any

注意:在 的情况下equals,就像在 Java 中一样,如果您切换参数,它可能不会返回相同的结果,例如1.equals(BigInt(1))将返回false逆将返回的位置true。这是因为每个实现只检查特定类型。原始数字不检查第二个参数是否为NumbernorBigInt类型,而仅检查其他原始类型

细节

AnyRef.equals(Any)方法是被子类覆盖的方法。Java 规范中的一种方法也被 Scala 所采用。如果在未装箱的实例上使用,它会被装箱以调用它(尽管在 Scala 中隐藏;在 Java 中使用int->更明显Integer)。默认实现仅比较引用(如在 Java 中)

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

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

例子

  • 1 equals 2将返回false,因为它重定向到Integer.equals(...)
  • 1 == 2将返回false,因为它重定向到Integer.equals(...)
  • 1 eq 2不会编译,因为它要求两个参数都是类型AnyRef
  • new ArrayList() equals new ArrayList()将返回true,因为它检查内容
  • new ArrayList() == new ArrayList()将返回true,因为它重定向到equals(...)
  • new ArrayList() eq new ArrayList()将返回false,因为两个参数都是不同的实例
  • foo equals foo将返回true,除非foonull,否则将抛出一个NullPointerException
  • foo == foo会回来true的,即使foonull
  • foo eq foo将返回true,因为两个参数都链接到同一个引用
于 2016-02-26T15:07:07.083 回答
8

==equalsforFloat和类型之间有一个有趣的区别Double:它们的处理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

因此,比较相等时的unboxedNan收益率false,因为这是 IEEE 浮点数定义它的方式,并且这应该在每种编程语言中都发生(尽管它以某种方式与身份的概念混淆)。

==当我们在比较对象引用时,盒装的 NaN 为在 Java 中使用的比较产生了 true 。

我没有对equals此案的解释,恕我直言,它的行为确实应该与==未装箱的双精度值相同,但事实并非如此。

翻译到 Scala 时,事情会稍微复杂一些,因为 Scala 已将原始类型和对象类型统一为Any并根据需要转换为原始 double 和盒装 Double。因此,scala==显然可以归结为原始NaN值的比较,但equals使用的是在装箱的 Double 值上定义的值(有很多隐式转换魔法正在进行,并且有一些东西被拉到双精度值上RichDouble)。

如果您真的需要找出是否实际NaN使用了某些东西isNaN

于 2016-02-05T14:12:35.500 回答
6

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

于 2016-12-26T13:02:45.453 回答