Java中修改char[][]副本时原数组被覆盖的问题求助
嗨,我完全懂你现在的困惑——明明maze是私有静态变量,只在初始化时赋值,之后没碰过它,怎么传给递归函数的mz参数后,修改mz居然把原maze给改了?这事儿跟C++指针没关系,核心是Java里引用类型的传递规则在起作用,咱们把这个事儿掰碎了说:
为什么修改mz会影响原maze?
Java里的数组(不管一维还是二维,比如你用的char[][])属于引用类型,和int、char这种基本类型不一样。当你把maze作为参数传给递归函数的mz时,传递的不是整个数组的副本,而是指向这个数组对象的引用的副本。
说白了,maze和mz现在就像两把钥匙,开的是同一个保险柜(数组对象在内存里的位置)。你用mz钥匙打开保险柜修改里面的东西,自然原maze钥匙打开看到的也是修改后的结果。
给你看个极简的例子就能明白:
private static char[][] maze = {{'#', '.'}, {'.', '#'}}; public static void solve(char[][] mz) { mz[0][1] = 'X'; // 这里修改的是和maze共享的那个数组对象 } public static void main(String[] args) { solve(maze); System.out.println(maze[0][1]); // 输出X,原数组确实被改了 }
怎么解决?给原数组做个深拷贝
要避免修改参数影响原数组,你需要在调用递归函数前,创建原maze的深拷贝,把拷贝后的数组传给递归函数。这样递归里修改的就是拷贝出来的新数组,原maze会完全保持原样。
针对你的char[][]二维数组,深拷贝可以这么实现:
// 工具方法:深拷贝二维char数组 private static char[][] deepCopyMaze(char[][] original) { if (original == null) return null; char[][] copy = new char[original.length][]; for (int i = 0; i < original.length; i++) { // 一维char数组用clone()就能完成元素级拷贝,因为char是基本类型 copy[i] = original[i].clone(); } return copy; }
然后调用递归的时候,别直接传maze,传拷贝后的数组:
// 原来的调用:solve(maze); // 修改成: char[][] mazeCopy = deepCopyMaze(maze); solve(mazeCopy);
这样递归函数里怎么折腾mazeCopy,原maze都不会受到任何影响啦。
补充说明
为啥用clone()就行?因为你的二维数组是char[][],每一行是一维char[],而char是基本类型,一维数组的clone()会创建一个新数组,把原数组的所有元素值复制过去,这对二维基本类型数组来说就是完整的深拷贝了。如果是引用类型的二维数组(比如String[][]),那还需要更细致的拷贝,但你的场景用这个方法完全足够。
内容的提问来源于stack exchange,提问作者Gam Boyo

