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

Jus*_*s12 137 scala equality scala-java-interop

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

实现是否与Java相同?

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

Did*_*ont 188

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

  • 更有趣的是,`3 == BigInt(3)`和`BigInt(3)== 3`都是真的.但是,`3.equals(BigInt(3))`是假的,而`BigInt(3).equals(3)`是真的.因此,更喜欢使用`==`.避免在scala中使用`equals()`.我认为`==`做了隐式转换,但是`equals()`没有. (23认同)
  • 确实如此.例如new java.util.ArrayList [Int]()== new java.util.ArrayList [Int](),因为ArrayList上的equals是内容相等. (19认同)
  • 它在使用Java库时是否也适用? (12认同)
  • 在Int和Long以及==与.equals()之间也存在一些奇怪的行为.与Int和Long相同的数字对于==返回true,对于equals返回false.所以==并不总是路由到等于. (5认同)

Don*_*oby 34

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

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


小智 26

TL; DR

  • 覆盖equals方法来比较每个实例的内容.这与equalsJava中使用的方法相同
  • 使用==运算符进行比较,无需担心null引用
  • 使用eq的方法来检查,如果两个参数是EXACTLY相同的参考.建议不要使用,除非您了解其工作原理,并且通常equals可以满足您的需求.并确保只使用AnyRef参数,而不仅仅是Any

注意:equals就像在Java中一样,如果切换参数,它可能不会返回相同的结果,例如1.equals(BigInt(1))将返回falseinverse将返回的位置true.这是因为每个实现仅检查特定类型.原始数字不检查,如果第二个参数是的Number,也不BigInt种,但只有其他基本类型

细节

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

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

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

例子

  • 1 equals 2false重定向返回Integer.equals(...)
  • 1 == 2false重定向返回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,因为两个参数都链接到相同的引用


scr*_*avy 5

有之间的有趣的差异==,并equalsFloatDouble类型:他们对待NaN不同的:

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

scala> Double.NaN equals Double.NaN
res4: Boolean = true
Run Code Online (Sandbox Code Playgroud)

编辑:正如指出的评论- “这也恰好在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));
}
Run Code Online (Sandbox Code Playgroud)

这将打印

false
true
true
Run Code Online (Sandbox Code Playgroud)

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

==当我们在比较对象引用时,带框的NaN对于在Java中使用的比较,会产生true 。

对于这种equals情况,我没有任何解释,恕我直言,它的行为应与未==装箱的double值相同,但事实并非如此。

转换为Scala后,问题变得更加复杂了,因为Scala将原始类型和对象类型统一Any为所需类型,并将原始类型和对象类型转换为原始double和盒装Double。因此,scala ==显然可以归结为原始NaN值的比较,但equals使用了在装箱的Double值上定义的值(存在很多隐式转换魔术,并且有很多东西用double压成double RichDouble)。

如果您真的需要找出是否确实NaN有用,请使用isNaN


jac*_*ack 5

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