Java方法内ArrayList引用重赋值未按预期生效问题咨询
问题核心原因
这个问题的本质是Java所有参数传递都是值传递,你对方法内形参的引用重赋值,不会影响方法外部的原始引用。
具体执行逻辑拆解
- 当main方法调用
removeDuplicated(testList)时,JVM会将main栈中testList持有的堆内存地址(也就是指向原始ArrayList对象的引用值)复制一份,传给removeDuplicated方法栈中的形参list。此时存在两个完全独立的引用变量同时指向堆里的原始testList对象:- main方法栈里的原始引用
testList - removeDuplicated方法栈里的局部形参
list
- main方法栈里的原始引用
- 方法内执行
list = distinctElements时,你修改的仅仅是removeDuplicated方法栈里那个局部形参的指向——让它从指向原始ArrayList,改为指向你新创建的去重后distinctElements对象。这个赋值操作完全触及不到main方法里的testList引用,它从始至终都指向最开始的原始ArrayList对象,没有发生任何改变。这也是为什么方法内紧接着打印list能看到去重结果:你打印的是形参当前指向的新对象,和外部的原始对象已经没有关联了。 - 你代码里的注释
//Sending list to garbage collector是完全错误的:原始ArrayList对象一直被main方法里的testList强引用着,根本不满足垃圾回收的可达性分析条件,自然不会被GC回收。只有当main方法里的testList引用也不再指向这个原始对象、且没有其他强引用关联时,它才会被标记为可回收对象。
正确实现去重的两种常见写法
- 直接修改原对象内容,不重新赋值引用:
public static void removeDuplicated(ArrayList<Integer> list) { ArrayList<Integer> distinctElements = new ArrayList<>(); for (Integer integer : list) { if (!distinctElements.contains(integer)) { distinctElements.add(integer); } } // 直接操作形参指向的原始list对象 list.clear(); list.addAll(distinctElements); }
- 将去重结果作为返回值返回,由外部调用方重新接收赋值:
public static ArrayList<Integer> removeDuplicated(ArrayList<Integer> list) { ArrayList<Integer> distinctElements = new ArrayList<>(); for (Integer integer : list) { if (!distinctElements.contains(integer)) { distinctElements.add(integer); } } return distinctElements; } // 调用处写法 testList = removeDuplicated(testList);
内容的提问来源于stack exchange,提问作者Sawyer
相关产品推荐
相关产品推荐

