==
与 .equals()
在 Scala 中的区别是什么?何时使用它们?
这两者在实现上是否与 Java 相同?
编辑:相关问题中讨论了特定情况下 AnyVal 的比较。更一般的情况是比较 Any。
==
与 .equals()
在 Scala 中的区别是什么?何时使用它们?
这两者在实现上是否与 Java 相同?
编辑:相关问题中讨论了特定情况下 AnyVal 的比较。更一般的情况是比较 Any。
通常使用 ==
,它会路由到equals
,但它会正确处理null
。引用相等性(很少使用)是eq
。
3 == BigInt(3)
和 BigInt(3) == 3
都是成立的。但是,3.equals(BigInt(3))
是错误的,而 BigInt(3).equals(3)
是正确的。因此,在Scala中最好使用==
而不是equals()
。我认为==
可以很好地进行隐式转换,但equals()
不能。 - Naetmulnew java.lang.Integer(1) == new java.lang.Double(1.0)
为真,而 new java.lang.Integer(1) equals new java.lang.Double(1.0)
为假? - Eastsunequals
方法以比较每个实例的内容。这是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
,因为两个参数链接到同一个引用==
是一个终态(final)方法,调用了.equals
方法,而该方法不是终态。
这与Java截然不同,Java中==
是一个运算符而非方法,且针对对象的严格比较引用相等性。
==
和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
。尽管它会影响标识的概念,但在每种编程语言中都应该如此。==
进行比较时,Java中的boxed NaN返回true,因为我们正在比较对象引用。equals
情况的解释,我认为它应该像未装箱的双精度值上的==
一样表现,但它并没有。Any
,并根据需要将其转换为基本double和装箱的Double类型。因此,Scala中的==
显然归结为原始NaN
值的比较,但equals
使用装箱Double值上定义的值(存在许多隐式转换魔法,并且由RichDouble
强化了某些属性)。NaN
,请使用isNaN
:
scala.Equals
中有一个scaladoc,它指向《Scala编程》第28章,对象相等性。 - Kyr