Java递归两种引用传递差异、深浅拷贝判断及使用场景问题
Java回溯引用传递问题解答
问题① 两种写法的拷贝类型说明
- 示例1中
res.add(temp)的写法没有做任何拷贝操作,只是将temp对象的内存引用直接存入结果集,你对原temp的所有修改都会同步影响结果集中的这条记录。 - 示例2中
res.add(new ArrayList(temp))的写法属于浅拷贝:它会创建一个新的ArrayList对象,新列表的元素和原temp的元素指向相同的内存地址,但两个列表本身是独立的对象,对原temp的增删操作不会影响新列表。
注意:这里没有深拷贝的实现,深拷贝需要递归拷贝集合中的所有元素对象,只有当集合存储可变自定义对象时才需要。本示例中元素是不可变的
Integer类型,浅拷贝完全满足需求。
问题② 第一个示例输出空列表的原因
你的判断完全正确:
整个递归过程中所有res.add(temp)添加的都是同一个temp对象的引用,递归回溯阶段执行temp.remove(temp.size()-1)会不断移除列表末尾元素,直到整个递归结束时temp会被清空,自然结果集里所有指向该对象的元素都会显示为空列表。
问题③ 递归中深浅拷贝的选择规则
你可以按照以下场景判断:
- 首先看被传递的对象后续是否会被修改:比如回溯算法里的临时缓存列表
temp,后续必然要执行回溯的删改操作,这种场景下只要你需要把当前状态的temp存入结果集,就必须做拷贝,不能直接传引用。 - 再看集合存储的元素类型:如果元素是不可变类型(比如
Integer、String、枚举类等),用浅拷贝就足够;如果元素是自定义的可变对象,且你后续可能会修改这些对象的属性,又不希望影响已经存入结果集的记录,就需要做深拷贝。 - 如果被传递的对象后续不会有任何修改:你可以直接传引用,不需要拷贝,能节省内存开销。
内容的提问来源于stack exchange,提问作者SHIVAM TYAGI
相关产品推荐
相关产品推荐

