Objects.equals(a, b)在项目开发中遇到过的坑:
// 避免被零除
Double total = 100D;
Double cost = 0D;
Double avg = 0D;
if (!Objects.equals(cost, 0)) {
avg = total / cost;
}
预期结果是cost值为0,因此不会执行第6行代码,但实际却执行并且报错了(修正:没有报错,但是avg = infinity,也不是我们想要的结果,不应该执行除的步骤)。
原因是:Objects.equals(a, b)源码如下
查看源码发现,比较了两次(也可能是一次):
1.首先比较对象的内存地址,如果一致,则不进行第二次比较,直接返回true;
2.如果对象的内存地址不一致,则a先判空,再调用对象的equals()方法。
我们再看一下对象的equals方法的源码:
上面是Double类重写的equals方法,首先会判断被比较的对象是不是Double类,如果不是则返回false;如果是,则比较值。所以会有本文一开始的问题,如果使用Objects.equals()方法比较的两个对象不是同一类,那么就会报错,而不会去比较他们的值。
所以本文一开始的代码,不管cost是不是0D都会进入if循环,导致除零报错。
解决办法:代码改为
if (!Objects.equals(cost, 0D)) { // 切记,比较的需要时相同的类
avg = total / cost;
}
或者,可以直接使用 != 号比较,风险会小一点,Double与int类型的值比较也可以。
if (cost != 0) {
avg = total / cost;
}
PS:Integer类有缓冲,范围是-128~127,Double类没有缓冲。
Double a = 0D;
Double d = 0D;
int f = 0;
boolean result = Objects.equals(a, d);
boolean result1 = Objects.equals(a, f);
System.out.println(result); // true
System.out.println(result1); // false
System.out.println(a == f); // true
System.out.println(a == d); // false 没有缓冲