【Java】复制List的引用传递和值传递

本文介绍了Java中List复制时遇到的引用传递问题,强调直接赋值会导致两个列表相互影响。通过举例说明了值传递的正确方式,包括使用`Collections.copy()`和`addAll()`方法,并提供了修复代码示例。在处理全局变量和局部变量时,确保正确复制数据以避免意外修改。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

List的复制

2021/11/8 周一

菜鸟程序员,很多知识点和坑之前学过,但实际用的时候却容易忽略。因为这个问题我在其他地方找了好久BUG,最后看到输出地址,才突然意识到这是引用传递,原来问题出在List的复制。


1. 结论

  • 直接用 newList = oldList引用传递,复制的是地址!!!!!!!
    改变oldList里的内容同样也会影响到newList

  • 值传递可以用Collections.copy(newList, oldList)
    但需要两个List的大小一样,即复制前还需要给newList指定长度

  • 我认为值传递更方便的是newList.addAll(oldList)

2. 业务需求
需要把readyData放到DataTable里以便前端展示,但readyData是个全局变量,显示完要清空,免得保留到下次又显示了。

3. 过程
于是就用一个临时的List即showData,来保存readyData里的内容,然后再清空readyData:

public TableDataInfo getActivationList(){
    List<ActivationForm> showData = readyData; // 引用传递
    readyData.removeAll(readyData); // 清空List
    System.out.println(showData);
    return getDataTable(showData);
}

但每次showData都没有内容,因为showData指向的还是readyData,而readyData被清空了

正确的复制应该是:

public TableDataInfo getActivationList(){
    List<ActivationForm> showData = new ArrayList<ActivationForm>();
    showData.addAll(readyData); // 值传递
    readyData.removeAll(readyData); // 清空List
    System.out.println(showData);
    return getDataTable(showData);
}
### JavaList 参数传递后排序失效的原因分析 在 Java 编程中,当通过方法调用将 `List` 类型作为参数传递时,可能会遇到排序操作无效的情况。这通常是由以下几个原因引起的: #### 1. **不可变集合** 如果传入的方法接收的是一个不可变集合(Immutable Collection),那么对该集合执行任何修改操作(如排序)都会抛出异常或者不生效。这是因为不可变集合的设计初衷是为了防止外部对其内容的更改[^3]。 #### 2. **浅拷贝问题** 即使传入了一个可变集合,在某些情况下可能只进行了浅拷贝而不是深拷贝。这意味着原始列表的内容并未真正被复制到新对象中,而是共享了相同的底层引用。因此,对副本的操作可能无法反映回原列表上。 #### 3. **未正确指定比较逻辑** 如果没有为 `sort()` 方法提供合适的 Comparator 实现,则可能导致排序行为不符合预期甚至看似无效果。例如,默认自然顺序可能并不适用于特定业务需求下的复杂对象排列。 --- ### 解决方案 针对上述提到的各种可能性及其对应场景,以下是几种有效的处理方式: #### 使用自定义 Comparator 进行显式排序 对于包含非基本类型的元素列表来说,应该明确定义如何对比两个项目之间的大小关系。下面展示了一种基于 Lambda 表达式的简洁写法来创建定制化的 comparator 并应用它完成排序过程: ```java import java.util.*; public class Main { public static void main(String[] args){ List<Person> people = Arrays.asList( new Person("Alice", 30), new Person("Bob", 25), new Person("Charlie", 35) ); Collections.sort(people, (p1,p2)-> p1.age - p2.age); System.out.println(people); } } class Person{ String name; int age; public Person(String n,int a){this.name=n;this.age=a;} @Override public String toString(){return "{name="+name+",age="+age+"}";} } ``` 此代码片段展示了如何利用 lambda 函数快速构建简单的整数差值计算规则用于年龄字段升序排列人员记录实例。 #### 创建深层克隆版本后再实施调整动作 为了避免因浅层复制而导致的行为偏差,建议先生成目标容器的一个全新独立实体再对其进行必要的变更活动。这样能够确保源数据保持不变的同时达到期望的效果。 ```java // 假设 originalList 是待加工的数据集 List<Integer> newList = new ArrayList<>(originalList); newList.sort((o1,o2)-> o1.compareTo(o2)); System.out.print(newList.toString()); ``` 这里演示了怎样借助构造器语法轻松获取一份完整的数组备份,并随后依据数值本身的特性安排其成员次序。 #### 验证输入是否允许变动 最后一步也是至关重要的环节就是确认所接受的对象确实具备编辑权限。可以通过尝试直接调用 add/remove/modify 等接口测试验证;另外也可以查阅官方文档了解具体类别的属性特征以及适用范围限制条件等信息。 --- ### 总结 综上所述,Java 列表参数经过函数传输之后可能出现排序失败的现象主要是由于三个方面造成的——即存在不可改变性质的目标群体、缺乏深入层次上的映射关联或者是缺少恰当的标准指引方向所致。为此提出了相应的改进措施包括但不限于制定专属评估体系标准、制造彻底分离出来的仿制品还有仔细审查初始素材能否承受相应程度的变化压力等方面加以改善优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值