Implementation of == and Object::equals
Remi Forax
forax at univ-mlv.fr
Tue Apr 9 11:09:21 UTC 2024
> From: "John Bossons" <jbossons at gmail.com>
> To: "valhalla-dev" <valhalla-dev at openjdk.org>
> Sent: Monday, April 8, 2024 4:30:44 AM
> Subject: Implementation of == and Object::equals
Hi John,
adding to what Roger said,
> I'm not sure that this is the right place to raise this, but don't know where
> else to do so.
> For identity types, == is simply a test of reference equality and so is a useful
> first test in an overriding type-specific equals method.
No, it's a bad idea performance-wise.
see https://youtu.be/kuzjX_efuDs?list=PLX8CzqL3ArzV4BpOzLanxd4bZr46x5e87
> For value types, the relationship is more subtle, since == is a test of value
> equality, not reference equality. I suggest it be implemented as an operator
> causing Object::equals to be invoked, so that if Object::equals is overloaded
> (e.g. to first test equality of hash codes or otherwise modify the default
> equals test), the overloaded method is automatically invoked when == is used.
> This would mean that Object::equals implements the == operator, rather than the
> reverse, so that a specification that a == b always means a.equals(b), whether
> implemented by the default test or by an overriding type-specific method (that
> e.g. tests for equality of identity object field values). I believe this would
> make value types (especially value trees) easier to use.
Two things, (1) the semantics of equals() on a class (value or identity) is stronger than the semantics of == on a value class, (2) what you propose introduce a circularity between == and equals, so if equals itslef uses ==, it's an infinite loop.
Imagine you have a value class defined like this:
value class MyValueClass {
String s;
public boolean equals(Object o) {
return o instanceof MyValueClass other && s.equals(other.s);
}
}
1) calling == on an instance of MyValueClass should check if s == other.s, not calling s.equals(other.s) on the field "field" so the semantics of == is different from the semantics of equals.
2) if we write equals like that and == calls equals()
public boolean equals(Object o) {
return this == o && o instanceof MyValueClass v && field.equals(v.field);
}
we have an infinite loop.
That's why == on value type is defined as doing == on each field and not as calling equals on each field.
That's said, in the future, for some value types, we may let users to be able to override == and identity hashCode so anyone can write it's own primitive type, but it will not be the default behavior and we are not there yet.
> John
regards,
Rémi
> --
> Phone: (416) 450-3584 (cell)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-dev/attachments/20240409/95a2672b/attachment.htm>
More information about the valhalla-dev
mailing list