Scala equality != Java Equality

Java developers will inevitably come across Scala at some point and say something like, “This is merely a simpler Java, with better functional support.”

Au contraire, my dear Java developer. There are far too many fundamental differences between Java and Scala for that statement to ever make sense. Take, for consideration, the simple matter of equality.

Java equality with “==” is unintuitive. It is littered with inconsistencies. Primitives are compared always by value. Objects are almost always compared by reference. Thus you have:

int x = 1;
int y = 1;
System.out.println(x == y); //prints true

Integer xObj = new Integer(1);
Integer yObj = new Integer(1);
System.out.println(xObj == yObj); //prints false

Furthermore, Java’s designers decided String instances should be interned which is a fancy way of saying the JVM caches instances of Strings so they can be reused. Thus, if you attempt to create a second new String instance with the same contents as one previously created, the JVM usually returns the previous instance again.

Therefore, you get the now-unexpected behavior that String objects evaluate true for an “==” comparison.

    String s = "Hello";
    String t = "Hello";
    System.out.println(s == t); //prints true

In other words, Java equality sucks.

Scala equality, on the other hand, is straightforward. There are no primitives in Scala. Everything is an object. It has one unified type system, and doesn’t need anything else. The same comparisons that were confusing in Java will behave as expected in Scala.

An example REPL output:

scala> val x = 1
x: Int = 1

scala> val y = 1
y: Int = 1

scala> x == y
res5: Boolean = true

scala> val s = "Hello"
s: String = Hello

scala> val t = "Hello"
t: String = Hello

scala> s == t
res7: Boolean = true

Even using Java types in Scala, you will see the new behavior:

scala> new java.lang.Integer(1)
res0: Integer = 1

scala> new java.lang.Integer(1)
res1: Integer = 1

scala> res0 == res1
res2: Boolean = true

Generally the “==” operator compares by value in Scala. For reference equality, the method “eq” can be used. It also has a negation “ne”. Both are inherited from the AnyRef superclass.

scala> val scott = new Person("Scott")
scott: Person = Person(Scott)

scala> val scott2 = new Person("Scott")
scott2: Person = Person(Scott)

scala> scott == scott2
res11: Boolean = true

scala> scott eq scott2
res12: Boolean = false

scala> scott ne scott2
res13: Boolean = true

There is one similarity, though. Strings in Scala are still interned, as in Java, so “eq” will return true usually for two String instances containing the same value.

scala> val s = "Hello"
s: String = Hello

scala> val t = "Hello"
t: String = Hello

scala> s eq t
res8: Boolean = true

Leave a Reply

Your email address will not be published. Required fields are marked *