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

问题描述 投票:0回答:5

Scala 中

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

实现和Java一样吗?

有一个类似的问题(为什么 == 运算符和 equals() 对于 Scala 中的 AnyVal 值的行为不同),但这是特定于

AnyVal
的。 这个问题涉及更一般的情况
Any

scala equals equality scala-java-interop
5个回答
225
投票

您通常使用

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


40
投票

TL;博士

  • 重写
    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
,然后调用装箱实例上的
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
    ,除非
    foo
    null
    ,然后会抛出
    NullPointerException
  • foo == foo
  • 将返回
    true
    ,即使
    foo
    null
  • foo eq foo
  • 将返回
    true
    ,因为两个参数都链接到相同的引用
    
        

38
投票
==

是最终方法,并调用

.equals
,这不是最终方法。

这与 Java 完全不同,其中

==

是一个运算符而不是方法,并且严格比较对象的引用相等性。

    


9
投票
==

equals
类型,
Float
Double
之间有一个有趣的区别:它们对待
NaN
的方式不同:

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

编辑:

正如评论中指出的那样 - “这也发生在 Java 中” - 取决于 this 到底是什么: 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 浮点数定义它的方式,并且这应该在每种编程语言中真正发生(尽管它在某种程度上与身份概念混淆)。

当我们比较对象引用时,在 Java 中使用

==

进行比较时,装箱的 NaN 会产生 true。


我没有对

equals

情况的解释,恕我直言,它确实应该与未装箱的双值上的

==
表现相同,但事实并非如此。

转换为 Scala,情况会稍微复杂一些,因为 Scala 将原始类型和对象类型统一为

Any

,并根据需要转换为原始双精度型和装箱双精度型。因此,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():Boolean

5
投票
==

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

© www.soinside.com 2019 - 2024. All rights reserved.