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。 原始数字不检查是否第二个参数是Number
或BigInt
types,但只有其他基本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
不会编译,因为它需要两个参数都是AnyRef
types -
new ArrayList() equals new ArrayList()
将返回true
,因为它检查内容 -
new ArrayList() == new ArrayList()
将返回true
,因为它redirect到equals(...)
-
new ArrayList() eq new ArrayList()
将返回false
,因为两个参数都是不同的实例 -
foo equals foo
将返回true
,除非foo
为null
,则会抛出NullPointerException
- 即使
foo
为null
,foo == foo
也会返回true
-
foo eq foo
将返回true
,因为这两个参数链接到相同的引用
==
和equals
Float
和Double
types之间有一个有趣的区别:它们以不同的方式处理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
, unboxedNan
产生了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方法