死循环(栈溢出)——深拷贝和浅拷贝的原因

死循环代码

 private List<Map<String, Object>> getJinJiangChildren(List<Map<String, Object>> list, String pcode) {
        List<Map<String, Object>> result = new ArrayList();
        //沿用ssx做法,和递归一个效果
        for (Map<String, Object> map : list) {
            if (pcode.equals(map.get("pcode"))) {
                    List<Map<String, Object>> cList = getJinJiangChildren(list, (String)map.get("code"));
                    if (CollectionUtil.isNotEmpty(cList)) {
                        //在头部添加
                        List<Map<String, Object>> tempList = new ArrayList<>();
                        tempList.add(map);
                        cList.addAll(0,tempList);
                        map.put("children", cList);
                    }
                    result.add(map);
            }
        }
        return result;
    }

报栈溢出。经分析,原因是(map是引用数据类型):

 tempList.add(map); 
 cList.addAll(0,tempList);  --cList里有tempList有map(引用,所有map扩大后,cList这个下标仍是指向这个扩大后的这个的map。最终导致for list的时候死循环了)
 map.put("children", cList);  -- map里有cList
                 

了解到:java 复制Map对象(深拷贝与浅拷贝)HashMap的putAll()实现了深拷贝。(Map.putAll()只是浅拷贝)

 private List<Map<String, Object>> getJinJiangChildren(List<Map<String, Object>> list, String pcode) {
        List<Map<String, Object>> result = new ArrayList();
        //沿用ssx做法,和递归一个效果
        for (Map<String, Object> map : list) {
            if (pcode.equals(map.get("pcode"))) {
                    List<Map<String, Object>> cList = getJinJiangChildren(list, (String)map.get("code"));
                    if (CollectionUtil.isNotEmpty(cList)) {
                        //在头部添加。  注意:不能直接tempList.add(map),会死循环(浅拷贝)
                        HashMap<String, Object> tempMap = new HashMap<>();
                        tempMap.putAll(map);
                        List<Map<String, Object>> tempList = new ArrayList<>();
                        tempList.add(tempMap);
                        cList.addAll(0,tempList);
                        map.put("children", cList);
                        System.out.println("------"+map.get("code"));
                    }
                    result.add(map);
            }
        }
        return result;
    }

-----------------Note----------------------

特殊引用类型却不会改变原值的(是因为都有final修饰嘛?), Note: 对于不可变对象(String, 基本类型的包装器, BigInteger和BigDecimal等)而言,如上例所示的deptName属性,修改前,原对象dept和拷贝对象copy虽然都是指向同一个String对象——“RD 1”,但是由于String为不可变对象,是无法修改原String的状态的,其会生成一个新的String对象——“RD 2”,并使引用变量指向其。
总结,深拷贝用法:
1.继承与重写(因为clone()是protected,包外调不到)
.clone()

implements Cloneable
//----------------------------------------
@Override
	public Object clone() {
		EhrWfStaffChangeEntity change = null;
		try {
			change = (EhrWfStaffChangeEntity) super.clone();
			//如果有引用类型&&非null需要clone,再层层clone ↓
		} catch (CloneNotSupportedException e) {
			return  null;
		}
		return change;
	}

2.如果存在引用类型属性,且不为空,需要层层嵌套到包装为止(如此,手动转深),否则只是地址引用,公用,谁变都变;如果本身被拷贝的是null,空指针,没有指向同一地址,则无需了(无法被牵连)。

  //补充默认信息当前端传null时 (但批量的操作时,ehrWfStaffChangeEntity是公用的会有问题。
  //所以clone下,但又因为业务所需是/需求是是只有空值需要重新赋值(副本有指向后并不会影响母本/正本——因为母本本就没有指向)、有值的本就公用,不需要深拷贝。恰好,所以这次只要最简单的clone重写即可)
  EhrWfStaffChangeEntity ehrWfStaffChangeEntity=(EhrWfStaffChangeEntity)change.clone();
  addDefaultFileldsWhenNull(ehrWfStaffChangeEntity,ehrStaffEntity);

https://zhuanlan.zhihu.com/p/130413565

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值