A little note on referential equality in Java

Alonso Del Arte
2 min readNov 20, 2020

Answering M. F. Hasler’s question, I casually tossed off the term “referential equality.” It’s one of those terms that I’ve come to take for granted, forgetting that sometimes it needs to be explained, even if the reader has a good idea what I meant.

Consider this Java unit testing toy example:

    @Test
public void testAdditionToyExample() {
int expected = 2;
int actual = 1 + 1;
assert expected == actual;
}

Suppose expected gets allocated in memory at 04F0 and actual gets allocated right after at 04F4. The memory allocations don’t matter for the assertion: expected and actual hold the same value, so the test passes, just as one would expect.

Now consider this other unit testing toy example:

    @Test
public void testStringToyExample() {
String phrase = "Hello, world!";
String expected = "hello, world!";
String actual = phrase.toLowerCase();

assert expected == actual;
}

Since both expected and actual hold “hello, world!”, we would expect the test to pass. But instead the assertion fails.

That’s because in Java, int is a primitive, String is a reference type, and the == operator works differently for reference types.

Let’s say expected was allocated at 32A1 BEC0 and actual at 2292 7A81. For a reference type like String, the == operator checks the pointers. In this case, they don’t match, so the assertion fails.

The only way this second assertion can pass is if expected and actual point to the exact same object.

In Java, every class has equals(), if nothing else, by inheritance from Object. But equals() just does a comparison with the == operator. By overriding equals(), a class like String can customize equals() to do something more useful.

Photo by Erol Ahmed on Unsplash

--

--

Alonso Del Arte
Alonso Del Arte

Written by Alonso Del Arte

is a Java and Scala developer from Detroit, Michigan. AWS Cloud Practitioner Foundational certified

No responses yet