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:and
Record#hashCode: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 (
==) inequalsso 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#equalsbut the latter could also be done using aninstanceof-check or something implemented natively.