I know, Java records
are value based, i.e. by default two records are equal if both records have the same values (compared to Java classes
where by default two classes are equal if their memory addresses are the same).
Am I right with the following assumption that this:
public record User(String name, Set<String> hobbies){}
is the same as this:
public record User(String name, Set<String> hobbies) {
@Override
public int hashCode() {
return Objects.hash(name, hobbies);
}
@Override
public boolean equals(Object obj) {
// check for "memory equality" (also in java records???)
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
// check for "value equality"
final User other = (User) obj;
return Objects.equals(name, other.name)
&& Objects.equals(hobbies, other.hobbies) ;
}
}
My question is:
Is my Equals/HashCode
implementation exactly the same as the automatic/generated Equals/HashCode
implementation? If I do not provide an Equals/HashCode
, then Java records adds a default one, but will it also include the check for "memory equality" or only does it only check for "value equality"?
This is implementation dependent.
If you take a look at the Javadoc of Record#equals
:
Apart from the semantics described above, the precise algorithm used in the implicitly provided implementation is unspecified and is subject to change
and Record#hashCode
:
The precise algorithm used in the implicitly provided implementation is unspecified and is subject to change within the above limits.
So, implementations are free to implement it however they want as long as they only use the components (and use all components).
However, most implementations will probably add a check for reference equality (==
) in equals
so that the other checks don't need to be done in case the objects are the same but you shouldn't rely on that.
The null check and the check that the argument is of the same type are necessary to obey to the contract of Object#equals
but the latter could also be done using an instanceof
-check or something implemented natively.