前言:
刚开始学习编程的时候,我们都会老老实实用 for-i循环,后面接触到for-each的时候,发现竟然还可以再省一点代码,慢慢也会开始学会用for-each。但其实,在有些即使是需要从头遍历的场景,for-each也并不能替代for-i循环,例如修改遍历基本数据类型的数组元素。
目录
一、分析数组类型:int[ ]
二、分析数组类型:String[ ]
三、分析StringBuilder[ ]类型,有时可以改
四、归纳总结:
一、分析数组类型:int[ ]
public static void main(String[] args) {
int[] numbers = new int[5];
System.out.print("修改前:");
//用for-each遍历输出,看看原数组
for (int number : numbers) {
System.out.print(number);
}
//用for-each遍历修改
for (int number : numbers) {
number=1;
}
System.out.println();
System.out.print("修改后:");
//用for-each遍历输出,看看修改结果
for (int number : numbers) {
System.out.print(number);
}
如图所示,修改失败。
原因:
当我们在
for-each
循环中遍历数组时,循环体中的变量(如上例中的number
)实际上只是数组元素的一个副本,而不是对原数组元素的引用。只是把number这个局部变量的值改了,循环体中的变量是一个局部变量,它的生命周期仅限于一次循环迭代。
为什么for-i行?
number[i]
通过索引访问的是数组中的实际元素的引用,修改它就会改变原数组中的数据。
二、分析数组类型:String[ ]
原因:
在
for-each
循环中,循环变量tmp
只是一个指向数组元素的局部引用。对tmp
重新赋值只会改变tmp
自身的指向,并不会修改数组中实际元素的引用,因此数组内容保持不变。
三、分析StringBuilder[ ]类型,有时可以改
原因:
append
方法可以修改StringBuilder
对象的内容,因为StringBuilder
是可变对象,append
直接改变对象的内部状态。而
=
赋值仅改变了tmp
变量的引用,指向了新的对象,不会影响原数组中的StringBuilder
对象,因此无法修改数组中的内容。
四、归纳总结:
1.针对基本数据类型:int[] 和其他基本数据类型的数组(如 byte[], char[], float[] 等)都具有相似的特性。在这些数组中,for-each`循环只会遍历元素的副本,而不是数组元素的引用,使用 for-each循环进行修改都不会影响原数组的内容。
2.针对引用类型:针对引用类型的数组,for-each`循环提供的是一个局部变量,该变量是数组中元素引用的拷贝。
- 如果在循环中使用 `=` 操作符,只会改变这个局部变量指向的对象引用,而不会影响原数组中的引用。
- 只有通过对这个对象调用方法,或者直接修改对象的属性(如 `TreeNode.next`),才能真正影响到原数组中的元素。
就像我们做一些链表Oj,题中链表头结点为head,
我们让cur=head;
再让cur=null;
并不会影响原链表。
但是我们让cur=head;
再让cur.next=null;
就影响到了原链表了。