☰ Contents Java Details

Classes and Equality

Student: So what else is different between records and classes? You said there was more.
Prof: One other big difference is equality.
Student: Equality?
Prof: Like == vs .equals(), and what those mean.
Student: Oh, so objects with classes don’t have .equals() or something?
Prof: Well… they kind of do.
Student: Kind of?
Prof: There is a default .equals() that every class gets, but it’s different from the one on records, and it just checks ==:
Student: So the .equals acts more like arrays’ equals method?
Prof: That’s right, it’s the default. If you want, you can define your own.
Student: You mean like, write my own equals method?
Prof: That’s right:
Student: Huh, that’s interesting. But why would you ever want that? Won’t it always just compare the fields with either == or .equals?
Prof: Great question. Consider this program:
Prof: Now, are r1 and r2 the same image?
Student: Yeah, obviously.
Prof: And should they be .equals()?
Student: Well obviously they should be… Oh right but the fields are arrays. So the record version won’t work.
Prof: Indeed! So Raster actually defines a .equals that provides this:
@Override
public boolean equals(Object other) {
    if (this == other) return true;
    if (!(other instanceof Raster r)) return false;
    if (this.width() != r.width() || this.height() != r.height()) return false;
    for (int y = 0; y < this.height(); y++) {
        if (!Arrays.equals(this.pixels[y], r.pixels[y])) return false;
    }
    return true;
}

Pict.java, lines 476–485

Prof: And that code is what compares the arrays in this example:
Student: I see. I feel like you’ve just brought up more questions though – what’s Object, and what’s instanceof and whats the Raster in parentheses doing?
Prof: Yeah, it’s a lot. Trust me, we’ll get there. For now, I just want you to see that we compare the pixels of the rasters in this equals method, and there wouldn’t be a way to define equals this way with a class or a record without writing equals ourselves.
Student: So we need .equals() for any comparisons between classes to be more than ==, and sometimes we need it to check something more than just comparing field by field.
Prof: Nice summary. It’s worth saying that our .equals() is cheating a little bit by not using Object, but that’s a lie I’ll make you live with a little longer.

Practice

Here is a class version of the image files from the search engine. Two ImageFiles should be equal when they have the same name and the same sizeKb. Fill in equals.

class ImageFile {
String name;
int sizeKb;
ImageFile(String name, int sizeKb) {
this.name = name;
this.sizeKb = sizeKb;
}
boolean equals(ImageFile other) {
return ;
}
}

ImageFile a = new ImageFile("cat.png", 300);
ImageFile b = new ImageFile("cat.png", 300);
boolean same = a.equals(b);
Why does equals compare the names with .equals, but the sizes with ==?
  1. name is a String, an object, and sizeKb is an int
    Strings are objects, so == would ask whether the two names are the same object, like the "trash panda" example from the memory chapter. ints are numbers, so == compares the numbers.
  2. name is a field, and sizeKb isn’t
    Both are fields. What matters is their types.
  3. == doesn’t compile on Strings
    == on two Strings compiles fine. It just asks a different question: are they the same object?