Java递归调用中变量作用域疑惑:集合参数为何能被修改?
Java递归中引用类型与基本类型的传递差异解析
Java里所有参数传递都是值传递,但引用类型和基本类型传递的"值"完全不是一回事,这就是你遇到两种不同结果的核心原因:
一、集合(引用类型)能被更新的原因
当你把generatePermutations里的result集合传入generatePermutationsRecursive时,传递的是该集合对象引用的副本——也就是说,递归方法里的result参数和外层方法的result变量,指向的是堆内存中同一个集合对象。
递归方法中调用result.add(...)这类操作,是直接对这个共享的集合对象进行修改,而非修改参数本身的引用值。所以外层方法的result变量指向的还是那个被修改后的集合,自然能拿到完整的排列结果。
举个简化的代码片段:
public class PermutationDemo { public static void main(String[] args) { List<List<Integer>> result = new ArrayList<>(); generatePermutationsRecursive(Arrays.asList(1,2,3), new ArrayList<>(), result); System.out.println(result); // 输出完整排列 } private static void generatePermutationsRecursive(List<Integer> nums, List<Integer> current, List<List<Integer>> result) { if (current.size() == nums.size()) { result.add(new ArrayList<>(current)); // 修改共享的集合对象 return; } for (int num : nums) { if (!current.contains(num)) { current.add(num); generatePermutationsRecursive(nums, current, result); current.remove(current.size() - 1); } } } }
二、基本类型变量无法更新的原因
而你测试的基本类型变量y,传递的是变量值的副本。递归方法里拿到的是一个全新的局部变量,它和外层的y没有任何关联——你在递归里修改这个副本的值,完全不会影响外层原变量的初始值。
比如这个示例:
public class BasicTypeDemo { public static void main(String[] args) { int y = 0; recursiveUpdate(y); System.out.println(y); // 输出0,原变量未被修改 } private static void recursiveUpdate(int y) { y++; // 修改的是方法内的副本变量 if (y < 5) { recursiveUpdate(y); } } }
这里每次递归调用时,都会把当前y的值复制一份传给下一层,下一层修改的只是自己的副本,外层的y全程没被碰过,所以最终还是初始值0。
总结
- 引用类型参数:传递的是对象引用的副本,多个变量指向同一个对象,修改对象内容会被所有引用感知。
- 基本类型参数:传递的是值的副本,方法内修改的是独立的局部变量,和原变量无关。
如果想让基本类型在递归中被更新,可以用以下几种方式:
- 把基本类型包装成引用类型(比如用
AtomicInteger,或者自己封装一个类) - 使用数组(数组是引用类型,传递数组引用的副本,修改数组元素会影响原数组)
内容的提问来源于stack exchange,提问作者isilia
相关产品推荐
相关产品推荐

