Reputation: 5162
Is there any design pattern (or idiom) that helps to implement equals()
method in Java?
That task is'n so hard but in most cases it's about the same... That's why I guess that there is a pattern but I didn't find it.
UPDATE
I chose the method: generate equals() method in Eclipse
but... I found a good way (in AbstractList) to make that generated code better:
if (!(attributes ==null ? other.attributes==null : attributes.equals(other.attributes)))
return false;
instead of generated:
if (attributes == null) {
if (other.attributes != null)
return false;
} else if (!attributes.equals(other.attributes))
return false;
Upvotes: 1
Views: 2335
Reputation: 5924
Regarding adding equals
and hashCode
for JPA/Hibernate entities, please see this StackOverflow Answer.
The code pattern recommended below depends upon the new instanceof
pattern matching functionality released for preview in Java 14 (2020/Mar/17), and then fully released in Java 16 (2021/Mar/16).
I really dislike seeing explicit uses of true
and false
, especially when they fall directly out of evaluated logic.
So, I am not at all fond of the default code pattern generated by my IDE (IntelliJ) when overriding and implementing equals()
in my classes.
It looks like this:
//Legacy laden pattern produced by IntelliJ code generator
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EqualsExampleClass that = (EqualsExampleClass) o;
return Objects.equals(stringy, that.stringy)
&& (inty == that.inty)
&& Objects.equals(bigIntegery, that.bigIntegery)
&& (booleany == that.booleany);
}
Encouraged by Oracle JEP 394 for the instanceof
pattern matching, I've refactored the above code to look like this:
//Modern flowing fluent style
@Override
public boolean equals(Object o) {
return (this == o) ||
((o instanceof EqualsExampleClass that)
&& (this.getClass() == that.getClass())
&& Objects.equals(this.stringy, that.stringy)
&& (this.inty == that.inty)
&& Objects.equals(this.bigInt, that.bigInt)
&& (this.booleany == that.booleany));
}
Per line execution details:
(this == o)
- checks for literally the same instance(o instanceof EqualsExampleClass that)
- checks to ensure o
is not null
, o
is an instance of this class (or a descendant), and if so, assigns o
to the narrowed type variable that
(this.getClass() == that.getClass())
- requires the equals comparison is between two instances of the same class (i.e., that
is not an instance of a descendant class), and can be removed if, and only if, this class is marked final
Objects.equals(this.stringy, that.stringy)
- is using Objects.equals()
on references (not primitives) to ensure that if either side returns a null
, the comparison is successfully made without throwing a NullPointerException
This code implementation pattern is considerably easier to functional flow read, analyze, reason about, and debug, during a refactoring pass.
Upvotes: 1
Reputation: 3288
Look at what Java Language Specification got to say.
equals
method just defines the notion of object equality
Apart from that there is no design pattern involved in designing this method. The truth is that equals
method is already designed by Java language designers and you can only make use of the design. If you are not confident of how to write your own equals method, consider taking the help of IDE's like eclipse which does the job for you.
Upvotes: 1
Reputation: 105
I always use following code:
if (null == obj) return false;
if (this == obj) return true;
if (!(object instanceof MyClass)) return false;
MyClass that = (MyClass) obj;
EqualsBuilder eb = new EqualsBuilder();
eb.append(this.businessKey, that.businessKey);
return eb.isEquals();
...
I never use technical keys like sequences or pk's, always business fields. Therefore I don't believe this can be made generic but must be made specific to any given Class.
Upvotes: 3
Reputation: 16158
Generally to implement equals() method, what I do is : I generate those from Eclipse as Eclipse can generate hashCode, toString and equals() methods very well.
Upvotes: 4
Reputation: 34367
Not sure about your expectation. equals()
is meant for defining your criteria of comparing two different objects of your class for equality.
In general, you compare each attribute one by one but its very much possible and supported that you do the comparison using fewer selected attributes only.
Upvotes: -1
Reputation: 36650
Maybe this helps: Implementing equals. Especially be aware of the close relationship betweeen hashcode() and equals(). Other than that, I suppose the concrete implementation of equals() really depends on your class design, means when do you treat two objects equal.
Upvotes: 1
Reputation: 16060
It is pretty much up to yourself to decide when two object are "the same" in a certain sense... Should they be equal when they contain the same data (perfectly valid usecase) or more strictly when they are the same physical object in memory (also valid) or just the same row in a DB when compared in a clustered environment?
Just remember to also override .hashCode()
or you're in for a world of hurt :-)
(Also, good article suggestions from @Andreas and @flash.)
Cheers,
Upvotes: 1