增强for循环原理详解

增强for循环

本质是采用了迭代器,并使用局部变量指向迭代器当前遍历到的元素,使用增强for循环时,无法修改集合当前索引位置的引用,但是如果元素是引用数据类型,那么是可以修改这个元素的信息的(String除外,因为String比较特殊,是不可变的,每次修改都会在常量池中新建一个对象出来)

测试遍历

java 复制代码
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循环进行修改元素值

java 复制代码
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循环所说的,"不能修改",是不能修改什么东西了吧,不能修改集合当前遍历到索引位置的值(你可以理解为,不能对这个集合进行任何的改动,比如删除元素,增加元素,修改指定索引位置上保存的引用)!而不是不能修改遍历到的元素内部信息。

相关推荐
繁依Fanyi10 分钟前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
慧都小妮子21 分钟前
Spire.PDF for .NET【页面设置】演示:打开 PDF 时自动显示书签或缩略图
java·pdf·.net
m512725 分钟前
LinuxC语言
java·服务器·前端
IU宝29 分钟前
C/C++内存管理
java·c语言·c++
瓜牛_gn30 分钟前
依赖注入注解
java·后端·spring
hakesashou31 分钟前
Python中常用的函数介绍
java·网络·python
佚先森40 分钟前
2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程
java·html
古月居GYH1 小时前
在C++上实现反射用法
java·开发语言·c++