What's the difference between == and .equals in Scala?
You normally use ==
, it routes to equals
, except that it treats null
s properly. Reference equality (rarely used) is eq
.
==
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.
TL;DR
- Override
equals
method to compare content of each instance. This is the sameequals
method used in Java - Use
==
operator to compare, without worrying aboutnull
references - Use
eq
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 eg 1.equals(BigInt(1))
will return false
where the inverse will return true
. This is because of each implementation checking only specific types. Primitive numbers dont check if the second argument is of Number
nor BigInt
types but only of other primitive types
Details
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 with int
->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 are null
, then it calls the equals(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 reference