今天踩了一个大大的坑,关于Java中Integer对象比较的问题!

程序员Feri一名12年+的程序员,做过开发带过团队创过业,擅长Java、嵌入式、鸿蒙、人工智能等,专注于程序员成长那点儿事,希望在成长的路上有你相伴!君志所向,一往无前!


问题

今天下班刚想溜,移动端的兄弟就火急火燎地跑过来:"Feri哥,快看看这个接口,返回数据的childs字段总是空的!"

我接过屏幕一看,好家伙,这数据结构分明是棵树,正常情况下childs里应该挂满叶子节点才对,可现在却光秃秃的,像被秋风扫过的树枝。

我心里一沉:"不可能啊,这个接口上线半年了,从来没出过问题。" 可事实就摆在眼前,接口确实返回了空数据。

排查过程

第一回合:代码审查

我迅速打开IDE,定位到数据组装的代码块:

if(type.getParentId()>0){
    //子类
    for(TypeItem i:items){
        System.err.println(i.getId()+"<---->"+type.getParentId()+"=="+(i.getId() == type.getParentId()));
        if(i.getId() == type.getParentId()){
            i.getChilds().add(item);
        }
    }
}else {
    items.add(item);
}

这段代码逻辑很清晰:如果当前节点有父节点,就把它添加到父节点的childs列表中;否则作为根节点。

仔细一看,问题出在这行:

if(i.getId() == type.getParentId())

第二回合:Integer的秘密

我一拍大腿:"原来是Integer比较的坑!" 这里的i.getId()type.getParentId()返回的都是Integer对象,而==比较的是对象引用,不是值!

为了验证我的猜想,我加了些调试日志:

System.err.println("i.getId()类型: " + i.getId().getClass());
System.err.println("type.getParentId()类型: " + type.getParentId().getClass());
System.err.println("i.getId()内存地址: " + System.identityHashCode(i.getId()));
System.err.println("type.getParentId()内存地址: " + System.identityHashCode(type.getParentId()));

运行后发现:

  • 当ID在-128~127之间时,两个对象的内存地址相同

  • 当ID大于127时,内存地址不同

这就解释了为什么之前测试一直正常——我们的测试数据ID都比较小,刚好落在Integer缓存范围内!

解决方案

==换成equals()方法:

if(type.getParentId()>0){
    //子类
    for(TypeItem i:items){
        System.err.println(i.getId()+"<---->"+type.getParentId()+"=="+(i.getId().equals(type.getParentId())));
        if(i.getId().equals(type.getParentId())){
            i.getChilds().add(item);
        }
    }
}else {
    items.add(item);
}

改完后重启服务,奇迹出现了:

childs字段终于有数据了,就像春天来了,光秃秃的树枝上又长出了新芽!

为什么会这样?

这要从Java的Integer缓存机制说起。Java为了优化性能,会缓存-128到127之间的Integer对象,就像一个"对象池"。当你创建这个范围内的Integer对象时,实际上是从缓存中拿的同一个对象。

举个栗子:

Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true,因为指向同一个缓存对象

Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false,因为超出缓存范围,创建了新对象

equals()方法会比较两个对象的值,不管它们是不是同一个对象:

System.out.println(c.equals(d)); // true,值都是200

总结

这个坑告诉我们:

  1. **Integer比较要用equals()**:比较值相等时,永远用equals(),除非你真的想比较对象引用

  2. 缓存机制要牢记:Java会缓存-128~127的Integer对象,超出范围就会创建新对象

  3. 测试数据要全面:测试时不仅要覆盖正常情况,还要考虑边界条件

最后送大家一句话:

程序就像江湖,每个程序员都是侠客。即使你是老江湖,也难免会踩坑。重要的是踩坑后能总结经验,成为更厉害的侠客!

下次遇到Integer比较,你还会掉坑里吗?评论区留言说说你遇到过的奇葩Bug吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值