Java数组左旋转:为何new int[]可行而直接赋值数组引用不行?
为什么Java中数组直接赋值引用和创建新数组的行为差异这么大?
Hey Vijay,这问题其实戳中了Java里数组(以及所有引用类型)的核心特性——引用传递,而非值传递,咱们一步步拆解清楚:
核心概念:Java数组是引用类型
在Java里,当你创建一个数组int[] a = new int[5];时,a并不是直接存储数组的所有元素,而是存储了一个指向内存中实际数组对象的地址(引用)。
你给出的对比代码刚好能直观体现两种写法的差异:
static int[] rotLeft(int[] a, int d) { int i = 0; int logicBreak = d; // 正确:创建独立的新数组 int[] copy = new int[a.length]; // 错误:引用赋值,和原数组共享内存 // int[] copy = a; while(logicBreak < a.length){ copy[i] = a[logicBreak]; i++; logicBreak++; } logicBreak = 0; while(logicBreak < d){ copy[i] = a[logicBreak]; i++; logicBreak++; } return copy; }
1. int[] copy = new int[a.length]; —— 正确的原因
这行代码做了两件事:
- 在内存中新建了一个完全独立的数组对象,长度和
a一致,但初始元素都是默认值0 - 把这个新数组的引用地址赋值给
copy变量
此时copy和a指向的是内存里两个完全分离的数组。你后续对copy的元素赋值操作,只会修改这个新数组,完全不会影响原数组a。所以你把a里的元素按左旋转逻辑拷贝到copy后,返回的就是正确的结果。
2. int[] copy = a; —— 出错的原因
这行代码并没有创建新数组,只是把a变量里存储的引用地址直接赋值给了copy。也就是说,copy和a现在指向的是内存中同一个数组对象!
哪怕你觉得自己覆盖了所有元素,也会因为共享数组而出错,咱们走一遍你的逻辑举例:
假设原数组a = [1,2,3,4,5],旋转次数d=2
- 第一个循环:
logicBreak从2开始,把a[2]=3赋值给copy[0],a[3]=4给copy[1],a[4]=5给copy[2]。但因为copy和a是同一个数组,原数组已经被改成了[3,4,5,4,5]! - 第二个循环:你想把原数组的前2个元素(原本是1,2)赋值给
copy[3]和copy[4],但此时原数组的前两个元素已经被第一个循环修改成了3和4,最终得到的数组是[3,4,5,3,4],完全不是预期的左旋转结果[3,4,5,1,2]。
两种写法的本质差异总结
| 写法 | 核心行为 | 内存状态 |
|---|---|---|
int[] copy = new int[a.length]; | 创建全新的独立数组 | 内存中存在两个数组对象,a和copy各指向一个 |
int[] copy = a; | 引用地址赋值 | 内存中只有一个数组对象,a和copy共享它 |
额外小提示
其实左旋转还可以实现原地旋转(不需要额外创建数组),不过那是进阶优化的话题。现在先把引用类型的核心概念吃透,以后写Java数组、对象相关的代码就不会踩这类坑啦~
内容的提问来源于stack exchange,提问作者Vijay
相关产品推荐
相关产品推荐

