Reputation: 5680
I have a class overriding hashCode(
) and equals()
-method. As I deal with BigDecimal
, I have to use compareTo()
instead of Objects.equals()
:
public class MyProduct extends Product{
private BigDecimal price;
@Override
public int hashCode() {
return Objects.hash(price);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true; // is this right or should this be deleted
if (obj == null || getClass() != obj.getClass()) return false;
final Product other = (Product) obj;
// is this right?
if (price == null ? (other.price != null) : price.compareTo(other.price) != 0) {
return false;
}
return super.equals(obj);
}
}
I have the following questions:
if (this == obj) return true;
from equals()
-method? Because with this line, the compareTo is not triggered and a wrong equals() could be computed, am I right?Upvotes: 1
Views: 1605
Reputation: 5680
I found the simplest way:
public static boolean isEqual(BigDecimal val1, BigDecimal val2) {
return val1 != null ^ val2 != null && val2 != null && val1.compareTo(val2) != 0;
}
and then use it within equals():
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final MyProduct other = (MyProduct) obj;
if(!isEqual(price, other.price)) return false;
return super.equals(obj);
}
Upvotes: 0
Reputation: 5680
I wrote an utitly method which can be used to compare two BigDecimals without throwing NPE:
// returns true, if val1 is the same as val2
// can this be improved ?
public static boolean isEqual(BigDecimal val1, BigDecimal val2) {
return !((val1 != null ^ val2 != null) || (val2 != null && val1.compareTo(val2) != 0));
}
This can be used within equals-method:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final MyProduct other = (MyProduct) obj;
if(!isEqual(price, other.price)) return false;
return super.equals(obj);
}
Upvotes: 0
Reputation: 1605
The first line is just an optimization meant to early return a result if both references point to the same object.
Is price
nullable? I assume it is, as you're checking for it within your equals()
implementation. In that case your code won't work in case other.price
will be null
. Specifically this code here:
price.compareTo(other.price) != 0
Will throw a NullPointerException
.
You can fix it like this:
@Override
public boolean equals(Object obj) {
if (this == obj) return true; // is this right or should this be deleted
if (obj == null || getClass() != obj.getClass()) return false;
final MyProduct other = (MyProduct) obj;
// If you prefer, the below two can be replaced with a single condition
// price != null ^ other.price != null
// Credits to @Andreas
if (price == null && other.price != null) {
return false;
}
if (price != null && other.price == null) {
return false;
}
if (other.price != null && price.compareTo(other.price) != 0) {
return false;
}
return super.equals(obj);
}
Now, you could probably make it shorter, but personally I find it the most readable this way.
Anyways, unless you really, really care about customising your equals()
implementation, I would suggest generating one with your IDE and sticking to it. They do a decent job most of the time and you don't have to worry about it being broken (although comparing BigDecimals
may be tricky for them, given you don't care about the scale but rather just the value).
Upvotes: 1