首先抛出结论:如果foreach循环操作的数据的类型是普通数据类型,则在foreach中修改数组内容无效;如果foreach循环操作的数据类型是引用类型,则修改数组内容有效。(建议:foreach只用于遍历,需要操作数组时直接使用传统的for循环较好)
接下来举例子说明:
(1) foreach循环操作的数据类型是普通数据类型:
String[] str1 = { "a", "b", "c" };
for (String str2 : str1) {
str2 = "d";
}
for (String string : str1) {
System.out.print(string);
}
这段代码运行结果是:abc,即第一个foreach循环中对str2进行的修改无效。
试试看将foreach循环转化为传统的for循环,即
for (String str2 : str1) {
str2 = "d";
}
//等同于↓
for(int i=0;i<str1.length;i++){
String str2=str1[i];
str2="d";
}
这样看应该就比较清晰了,当使用foreach循环来迭代访问数据元素时,foreach中的循环变量相当于一个临时变量,系统会把数组元素依次赋值给这个临时变量,但其实这个临时变量并不是我们数组中的元素,因此,str2="d"相当于对临时变量进行修改,并不会修改到数组的元素值。
(2)foreach循环操作的数据类型是引用类型:
首先创建一个User类:
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" + "id=" + id + ", name='" + name + '\'' + '}';
}
}
public static void main(String[] args) {
User user=new User(1,"aa");
User user1=new User(2,"bb");
List<User> list=new ArrayList<User>();
list.add(user);
list.add(user1);
for(User user2:list){
System.out.println("修改前:"+user2.toString());
user2.setId(3);
user2.setName("cc");
}
for(User user2:list){
System.out.println("修改后:"+user2.toString());
}
}
这段代码的运行结果是:
我们发现,这次修改是成功的。原因是Object对象的真实数据存储在堆内存中,它在栈内存中存储的是变量名和内存地址。这个user2存的是从list中传过来的一个真正的对象的地址,如果你修改这个对象的属性值,list里面对应对象也会改变。