因为这个Bug,额外多花了0.5h排查问题。
需要节省时间的粉丝继续:
上面的招式都是CleanCode一书讲的标准套路,可是,居然也出了bug!!!
你说,找谁评理去!!!
哪位粉丝朋友看到是错在哪了?
所以之后的比较都改成了Objects.equals。之后惨案发生了
就是这个地方出问题了:
化繁为简,来换个写法,复现下这个Bug:
直接看结果:
源码见文末
为什么呢?
使用Objects.equals(Object a,Object b)方法判断两个值是否相等时,一定要保证两个入参的类型要一致。 否则即使两个值相同,但其结果仍然会返回false。
知其然,也要知其所以然。 上源码【Show the code】: java.util.Objects#equals
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
Integer常量池中的1和Long常量池中的1不是同一个对象。 虽然它们的值相同,但它们属于不同类型的常量池,所以Integer类型1的对象地址 != Long类型1的对象地址。即a!=b
此处a是1,不为null
在本例中,a是Integer类型,所以java.lang.Integer#equals
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
b是Long类型,直接return false;
结论: (Objects.equals(1, 1L)).isFalse成立
除此之外,还有Long、Byte、Short、Double、Float、Boolean和Character也有类似的equals方法判断逻辑。
【碎碎念】 写业务代码时,常踩坑的场景: Long类型和Integer类型比较,比如:用户id的场景。 Byte类型和Integer类型比较,比如:状态判断的场景。 Double类型和Integer类型比较,比如:金额为0的判断场景。
import org.junit.jupiter.api.Test;
import java.util.Objects;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @Auther: cheng.tang
* @Date: 2024/7/5
* @Description: tool-box
*/
public class ObjectsEqualsTest {
@Test
public void equalsTest() {
assertThat(Objects.equals(1, 1L)).isFalse();
}
}
这两天的上海也热起来了,昨天晚上没盖被子也热醒了二次