增强for循环
本质是采用了迭代器,并使用局部变量指向迭代器当前遍历到的元素,使用增强for循环时,无法修改集合当前索引位置的引用,但是如果元素是引用数据类型,那么是可以修改这个元素的信息的(String除外,因为String比较特殊,是不可变的,每次修改都会在常量池中新建一个对象出来)
测试遍历
public static void main(String[] args) {
List list=new ArrayList();
list.add("a");
list.add("f");
list.add("j");
list.add("k");
//使用增强for循环遍历集合
for (Object value:list){
System.out.println(value);
}
}
增强for循环的局部变量仅用于接收集合元素,修改obj的值并不能修改集合元素(或者说,不能修改对应的集合索引的引用),想要修改只能用集合里面的方法,其实增强for循环内部仍然使用了迭代器。因为增强for循环获取的仅仅是集合的副本,因此是无法对集合更新的。
看了下面的原理图你应该会理解的:
原理图
总结
所以我们与其说是副本,不如说又新建了一个变量,去引用迭代器遍历到的值,如果元素是基本数据类型则保存的仅仅是值,如果是引用数据类型,就是保存的是地址,我们可以使用这个地址对对应的对象进行操作的,比如修改这个对象的属性等。
但是上面例子中,元素是字符串"",是不可变的,因此增强for循环的局部变量引用是指向了字符串常量池,对这个字符串的更新,会在字符串常量池新创造一个字符串的对象,并不会影响遍历到的元素的内容。
如果是stringBuffer或者StringBuilder,我们使用append方法去修改,是可以修改成功的。而为什么我们无法修改当前遍历到的索引的元素,你难道没发现吗,我们缺少了一个索引啊(所以如果我们要修改集合对应位置的引用,可以使用普通for循环,也可以使用迭代器,迭代器的索引是内置的,不对外暴露,因此我们可以直接使用迭代器.remove去移除当前遍历到的元素),但是依然不建议在增强for循环当中去修改集合的引用。
为了验证我上面的结论,这里我演示一遍使用stringBuffer来测试增强for循环进行修改元素值
public class MyTest {
public static void main(String[] args) {
List<StringBuffer> list =new ArrayList<StringBuffer>();
list.add(new StringBuffer("hello"));
list.add(new StringBuffer("tsdfa"));
list.add(new StringBuffer("fdasfh"));
list.add(new StringBuffer("wrodl"));
//增强for
for (StringBuffer stringBuffer : list) {
//这里我把每一个stringBuffer元素的内容都清除掉(把所有字符都替换成空串,相当于清除)
stringBuffer.replace(0,stringBuffer.length(), "");
//然后拼上新的内容
stringBuffer.append("111111111");
}
//再遍历一遍
for (int i=0;i<list.size();i++){
System.out.println(list.get(i).toString());
}
}
}
运行结果
到此,你应该能理解增强for循环所说的,“不能修改”,是不能修改什么东西了吧,不能修改集合当前遍历到索引位置的值(你可以理解为,不能对这个集合进行任何的改动,比如删除元素,增加元素,修改指定索引位置上保存的引用)!而不是不能修改遍历到的元素内部信息。