In the scaladoc of scala.Any
, the operator ==
(or, method ==
) is explained:
The expression
x == that
is equivalent toif (x eq null) that eq null else x.equals(that)
http://www.scala-lang.org/api/current/#scala.Any
For objects of subclasses of AnyRef
, I can understand it easily, and I didn't see any strange things.
However, for values of AnyVal
, (I mean Int
, Double
, Long
, and so on,) the above definition is somewhat tricky (1 eq null
? This does not compile if we do not convert 1
to java.lang.Integer). Also, ==
and equals()
behave differently.
I'll give some examples.
scala> 1 == 1 res0: Boolean = true scala> 1 == 1.0 res1: Boolean = true scala> 1 == 1.2 res2: Boolean = false scala> 2 == BigInt(2) res3: Boolean = true scala> 2.0 == BigInt(2) res4: Boolean = true scala> 2 == BigInt(3) res5: Boolean = false
So far, nothing is strange. But if we do the same things with equals()
methods,
scala> 1 equals 1 res7: Boolean = true scala> 1 equals 1.0 res8: Boolean = false scala> 1 equals 1.2 res9: Boolean = false scala> 2 equals BigInt(2) res10: Boolean = false scala> 2.0 equals BigInt(2) res11: Boolean = false scala> 2 equals BigInt(3) res12: Boolean = false
So if the types are different, equals() always returns false, whereas == tests if they represent the same value if they are converted to the same type.
In the case of subclass of AnyRef
, methods ==
and equals()
return the same.
scala> BigInt(2) == 2 res25: Boolean = true scala> BigInt(2) == 2.0 res26: Boolean = true scala> BigInt(3) == 2 res27: Boolean = false scala> BigInt(2) equals 2 res28: Boolean = true scala> BigInt(2) equals 2.0 res29: Boolean = true scala> BigInt(3) equals 2 res30: Boolean = false
So, why methods ==
and equals()
are diffrent for AnyVal
?
I'm using Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_25).
EDIT 1
I saw that == cannot be overriden directly, as it is defined as a final method in class Any according to Programming in Scala, 2nd Edition.
EDIT 2
Although there is an answer, my question remains. I will leave this question open.
What correspond to scala.Int
and scala.Long
in Java are Java's primitive types int
and long
.
In Java, java.lang.Integer
and java.lang.Long
are classes, so their variables are references, which can have null
.
That means, they are like AnyRef
in Scala. Not AnyVal
.
Scala's AnyVal
- scala.Int
and scala.Long
cannot have null
values, neither can Java's int
and long
.
Also, java.lang.Integer
's ==
in Java is for reference equality (same as eq
in Scala).
What you get using java.lang.Integer
in Scala REPL will be quite different from what you get with it in pure Java Project with .java source file in this respect.
However, what I could get from using classes of primitive types in Java was: (THIS IS JAVA)
class Main {
public static void main(String[] args) {
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1L)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1.0)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(new java.lang.Integer(1))));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(new java.lang.Long(1))));
}
}
output:
true false false true falseYes, they behave similar to scala AnyVal's
equals()
. But, then, why does this happen?
Does Scala's AnyVal
's ==
correspond to ==
of Java's primitive type
and does Scala's AnyVal's equals()
correspond to equals()
of Java's class types?
What about equality tests with BigInt? There is no corresponding primitive type in Java.
The question remains...
EDIT 3
I could find some information from scaladoc. (http://www.scala-lang.org/api/current/index.html#scala.Int)
The Implicit information from the item of Shadowed Implicit Value Members,
I could find ==
was overloaded for Char
, Short
, Float
, and ...,
and ==
will call implicit conversions int2double
, int2float
, or int2long
.
Whereas equals()
is only defined for Any
, and it will call implicit conversion int2Integer
.
That is, Int.equals()
will be the same as java.lang.Integer.equals()
.
One question remains:
Why ==
of AnyVal
is overloaded, and equals()
of AnyVal
is not overloaded?