What is the difference between ==
and .equals()
in Scala, and when to use which?
Is the implementation same as in Java?
EDIT: The related question talks about specific cases of AnyVal
. The more general case is Any
.
What is the difference between ==
and .equals()
in Scala, and when to use which?
Is the implementation same as in Java?
EDIT: The related question talks about specific cases of AnyVal
. The more general case is Any
.
You normally use
==
, it routes toequals
, except that it treatsnull
s properly. Reference equality (rarely used) iseq
.TL;DR
equals
method to compare content of each instance. This is the sameequals
method used in Java==
operator to compare, without worrying aboutnull
referenceseq
method to check if both arguments are EXACTLY the same reference. Recommended not to use unless you understand how this works and oftenequals
will work for what you need instead. And make sure to only use this withAnyRef
arguments, not justAny
NOTE: On the case of
equals
, just as in Java, it may not return the same result if you switch the arguments eg1.equals(BigInt(1))
will returnfalse
where the inverse will returntrue
. This is because of each implementation checking only specific types. Primitive numbers dont check if the second argument is ofNumber
norBigInt
types but only of other primitive typesDetails
The
AnyRef.equals(Any)
method is the one overridden by subclasses. A method from the Java Specification that has come over to Scala too. If used on an unboxed instance, it is boxed to call this (though hidden in Scala; more obvious in Java withint
->Integer
). The default implementation merely compares references (as in Java)The
Any.==(Any)
method compares two objects and allows either argument to be null (as if calling a static method with two instances). It compares if both arenull
, then it calls theequals(Any)
method on boxed instance.The
AnyRef.eq(AnyRef)
method compares only references, that is where the instance is located in memory. There is no implicit boxing for this method.Examples
1 equals 2
will returnfalse
, as it redirects toInteger.equals(...)
1 == 2
will returnfalse
, as it redirects toInteger.equals(...)
1 eq 2
will not compile, as it requires both arguments to be of typeAnyRef
new ArrayList() equals new ArrayList()
will returntrue
, as it checks the contentnew ArrayList() == new ArrayList()
will returntrue
, as it redirects toequals(...)
new ArrayList() eq new ArrayList()
will returnfalse
, as both arguments are different instancesfoo equals foo
will returntrue
, unlessfoo
isnull
, then will throw aNullPointerException
foo == foo
will returntrue
, even iffoo
isnull
foo eq foo
will returntrue
, since both arguments link to the same referenceIn Scala == first check for Null values and then calls equals method on first object
There is an interesting difference between
==
andequals
forFloat
andDouble
types: They treatNaN
differently:Edit: As was pointed out in a comment - "this also happens in Java" - depends on what exactly this is:
This will print
So, the
unboxedNan
yieldsfalse
when compared for equality because this is how IEEE floating point numbers define it and this should really happen in every programming language (although it somehow messes with the notion of identity).The boxed NaN yields true for the comparison using
==
in Java as we are comparing object references.I do not have an explanation for the
equals
case, IMHO it really should behave the same as==
on unboxed double values, but it does not.Translated to Scala the matter is a little more complicated as Scala has unified primitive and object types into
Any
and translates into the primitive double and the boxed Double as needed. Thus the scala==
apparently boils down to a comparison of primitiveNaN
values butequals
uses the one defined on boxed Double values (there is a lot of implicit conversion magic going on and there is stuff pimped onto doubles byRichDouble
).If you really need to find out if something is actually
NaN
useisNaN
:==
is a final method, and calls.equals
, which is not final.This is radically different than Java, where
==
is an operator rather than a method and strictly compares reference equality for objects.