Equal objects
== compares references
When are two objects the same? Here are two theater seats, both in row B, seat 7:
public class Main {
public static void main(String[] args) {
Seat mine = new Seat("B", 7);
Seat yours = new Seat("B", 7);
Seat same = mine;
System.out.println(mine == yours);
System.out.println(mine == same);
System.out.println(mine.equals(yours));
}
}public class Seat {
private String row;
private int number;
public Seat(String row, int number) {
this.row = row;
this.number = number;
}
public String toString() {
return this.row + this.number;
}
}false
true
false- As in module 22,
==on two objects asks whether both variables refer to the same object.mineandyourswere made by twonews, so they're two objects, even though what's in them is the same.Seat same = mine;copies the reference, somine == sameis true. - Seat has no method called
equals, yetmine.equals(yours)compiles. Every class gets a few methods from Java without writing them, among themtoStringandequals. ThetoStringit gets gives the class name and a code (module 18), and theequalsit gets does the same as==.
You've met this with Strings: == asks whether two Strings are the same object, while equals compares their letters. That's why text is always compared with equals. To make equals compare the contents of your own objects, the class writes its own equals, just as it writes its own toString.
Writing equals
Two seats are equal when they have the same row and the same number. Here's the equals method for Seat:
public boolean equals(Object compared) {
if (this == compared) {
return true;
}
if (!(compared instanceof Seat)) {
return false;
}
Seat other = (Seat) compared;
return this.row.equals(other.row) && this.number == other.number;
}
Line by line:
- The header must be exactly
public boolean equals(Object compared).Objectis Java's type for any object at all, soequalscan be given a Seat, a String, a list or anything else. Java's own methods, such as a list'scontainsin the next step, use only anequalswith exactly this header. (The parameter's name can be anything;comparedis a common one.) if (this == compared): when it's the very same object, it's certainly equal, and nothing else needs checking.compared instanceof Seatis true whencomparedis a Seat object. Anything else, such as a String, can't be equal to a seat, so the method returnsfalse.instanceofis false fornulltoo, soseat.equals(null)givesfalsewithout a crash.Seat other = (Seat) compared;is a cast.comparedis a Seat, but its type says onlyObject, and an Object has norowornumber. The cast lets the code use it as a Seat. It's safe here, because the line before made sure it is one.- The last line compares the contents: Strings with
equals, numbers with==. As in the previous step,other.rowmay read the private variables, because this code is in the Seat class.
With the method in the class:
public class Main {
public static void main(String[] args) {
Seat mine = new Seat("B", 7);
Seat yours = new Seat("B", 7);
Seat next = new Seat("B", 8);
System.out.println(mine == yours);
System.out.println(mine.equals(yours));
System.out.println(mine.equals(next));
System.out.println(mine.equals("B7"));
}
}public class Seat {
private String row;
private int number;
public Seat(String row, int number) {
this.row = row;
this.number = number;
}
public boolean equals(Object compared) {
if (this == compared) {
return true;
}
if (!(compared instanceof Seat)) {
return false;
}
Seat other = (Seat) compared;
return this.row.equals(other.row) && this.number == other.number;
}
public String toString() {
return this.row + this.number;
}
}false
true
false
false== still says false: mine and yours are two objects. But equals now compares what's in them, and says they're equal. A String is never equal to a seat, even when it looks like the seat printed out: "B7" doesn't pass the instanceof check.
What counts as equal is up to the class. Two seats are equal when the row and the number match. A class for library members might say two members are equal when their membership numbers match, whatever names they were written down with.
Newer versions of Java can do the instanceof check and the cast in one go (compared instanceof Seat other), but in this course they're written as two separate steps.