Scala中==和.equals之间的区别是什么?

时间:2011-10-06 22:23:47

标签: scala equality scala-java-interop

Scala中==.equals()之间的区别是什么,以及何时使用哪个?

实现是否与Java相同?

编辑:相关问题涉及AnyVal的具体案例。更一般的情况是Any

5 个答案:

答案 0 :(得分:179)

您通常使用==,它会路由到equals,但会正确处理null。引用相等(很少使用)是eq

答案 1 :(得分:33)

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

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

答案 2 :(得分:26)

TL; DR

  • 覆盖equals方法以比较每个实例的内容。这与Java中使用的equals方法相同
  • 使用==运算符进行比较,而不必担心null引用
  • 使用eq方法检查两个参数是否都是完全相同的引用。建议不要使用,除非您了解其工作原理,equals通常可以满足您的需求。并确保仅将其用于AnyRef个参数,而不仅仅是Any

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

详细

AnyRef.equals(Any)方法是由子类重写的方法。 Java规范中的一种方法也已经出现在Scala中。如果在未装箱的实例上使用,则将其装箱以调用此方法(虽然隐藏在Scala中;在Java中使用int更明显 - > Integer)。默认实现仅比较引用(如在Java中)

Any.==(Any)方法比较两个对象,并允许任一参数为null(就像调用带有两个实例的静态方法一样)。它会比较两者是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,因为两个参数都链接到相同的参考

答案 3 :(得分:5)

对于"bin": { "csp": "es5/bin/csp.js" }, ==类型,equalsFloat之间存在一个有趣的区别:它们对Double的处理方式不同:

NaN

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

scala> Double.NaN == Double.NaN
res3: Boolean = false

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

这将打印

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,因为这是IEEE浮点数定义它的方式,这应该在每种编程语言中实现(尽管它在某种程度上与身份的概念混淆) )。

当我们比较对象引用时,盒装的NaN在Java中使用false得到的结果为true。

我没有==案例的解释,恕我直言,它实际上应该与未装箱的双值上的equals相同,但事实并非如此。

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

如果您确实需要查明某些内容是否真的RichDouble使用NaN

答案 4 :(得分:1)

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