我有一个覆盖hashCode(
和equals()
方法的类。在处理BigDecimal
时,我必须使用compareTo()
而不是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);
}
}
我有以下问题:
if (this == obj) return true;
方法中删除行equals()
?因为在这一行中,compareTo不会被触发并且可以计算出错误的equals(),对吗?答案 0 :(得分:1)
第一行只是一个优化,旨在在两个引用都指向同一对象时尽早返回结果。
price
是否可以为空?我认为是这样,因为您正在equals()
实现中对其进行检查。在这种情况下,如果other.price
为null
,则您的代码将无法工作。具体代码如下:
price.compareTo(other.price) != 0
会抛出一个NullPointerException
。
您可以这样解决它:
@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);
}
现在,您可以将它缩短一些,但就我个人而言,这种方式最易读。
无论如何,除非您真的非常在乎自定义equals()
实现,否则我建议您使用IDE生成一个并坚持使用。他们大多数时候的表现不错,您不必担心会被打破(尽管比较BigDecimals
对他们来说可能很棘手,因为您不在乎规模,而只是在乎价值)
答案 1 :(得分:0)
我写了一个非常实用的方法,可以用来比较两个BigDecimal,而不会抛出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));
}
这可以在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);
}
答案 2 :(得分:0)
我找到了最简单的方法:
public static boolean isEqual(BigDecimal val1, BigDecimal val2) {
return val1 != null ^ val2 != null && val2 != null && val1.compareTo(val2) != 0;
}
,然后在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);
}