Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy == operator and equals() behave differently for values of AnyVal in Scala
    primarykey
    data
    text
    <p>In the scaladoc of <code>scala.Any</code>, the operator <code>==</code> (or, method <code>==</code>) is explained:</p> <blockquote> <p>The expression <code>x == that</code> is equivalent to <code>if (x eq null) that eq null else x.equals(that)</code> <a href="http://www.scala-lang.org/api/current/#scala.Any">http://www.scala-lang.org/api/current/#scala.Any</a></p> </blockquote> <p>For objects of subclasses of <code>AnyRef</code>, I can understand it easily, and I didn't see any strange things.</p> <p>However, for values of <code>AnyVal</code>, (I mean <code>Int</code>, <code>Double</code>, <code>Long</code>, and so on,) the above definition is somewhat tricky (<code>1 eq null</code>? This does not compile if we do not convert <code>1</code> to java.lang.Integer). Also, <code>==</code> and <code>equals()</code> behave differently.</p> <p>I'll give some examples.</p> <pre> 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 </pre> <p>So far, nothing is strange. But if we do the same things with <code>equals()</code> methods,</p> <pre> 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 </pre> <p>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.</p> <p>In the case of subclass of <code>AnyRef</code>, methods <code>==</code> and <code>equals()</code> return the same.</p> <pre> 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 </pre> <p>So, why methods <code>==</code> and <code>equals()</code> are diffrent for <code>AnyVal</code>?</p> <p>I'm using Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_25).</p> <p><strong>EDIT 1</strong><br/> I saw that == cannot be overriden directly, as it is defined as a final method in class Any according to <a href="http://rads.stackoverflow.com/amzn/click/0981531644">Programming in Scala, 2nd Edition</a>.</p> <p><strong>EDIT 2</strong><br/> Although there is an answer, my question remains. I will leave this question open.<br/> <br/> What correspond to <code>scala.Int</code> and <code>scala.Long</code> in Java are Java's primitive types <code>int</code> and <code>long</code>.<br/> In Java, <code>java.lang.Integer</code> and <code>java.lang.Long</code> are classes, so their variables are references, which can have <code>null</code>. That means, they are like <code>AnyRef</code> in Scala. Not <code>AnyVal</code>.<br/> Scala's <code>AnyVal</code> - <code>scala.Int</code> and <code>scala.Long</code> cannot have <code>null</code> values, neither can Java's <code>int</code> and <code>long</code>.<br/> Also, <code>java.lang.Integer</code>'s <code>==</code> in Java is for reference equality (same as <code>eq</code> in Scala).<br/> What you get using <code>java.lang.Integer</code> in Scala REPL will be quite different from what you get with it in pure Java Project with .java source file in this respect.<br/> <br/> However, what I could get from using classes of primitive types in Java was: (THIS IS JAVA)</p> <pre><code>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)))); } } </code></pre> <p>output:<br/><pre> true false false true false</pre> Yes, they behave similar to scala AnyVal's <code>equals()</code>. But, then, why does this happen?</p> <p>Does Scala's <code>AnyVal</code>'s <code>==</code> correspond to <code>==</code> of Java's primitive type<br/> and does Scala's AnyVal's <code>equals()</code> correspond to <code>equals()</code> of Java's class types?<br/> What about equality tests with BigInt? There is no corresponding primitive type in Java.<br/> The question remains...</p> <p><strong>EDIT 3</strong><br/> I could find some information from scaladoc. (<a href="http://www.scala-lang.org/api/current/index.html#scala.Int">http://www.scala-lang.org/api/current/index.html#scala.Int</a>)<br/> The <em>Implicit information</em> from the item of <em>Shadowed Implicit Value Members</em>,<br/> I could find <code>==</code> was overloaded for <code>Char</code>, <code>Short</code>, <code>Float</code>, and ...,<br/> and <code>==</code> will call implicit conversions <code>int2double</code>, <code>int2float</code>, or <code>int2long</code>.<br/> Whereas <code>equals()</code> is only defined for <code>Any</code>, and it will call implicit conversion <code>int2Integer</code>.<br/> That is, <code>Int.equals()</code> will be the same as <code>java.lang.Integer.equals()</code>.<br/> <br/> One question remains:<br/> Why <code>==</code> of <code>AnyVal</code> is overloaded, and <code>equals()</code> of <code>AnyVal</code> is not overloaded?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload