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

相关推荐
Tigshop开源商城4 小时前
『物流设置+SEO优化』Tigshop开源商城系统 JAVA v5.8.26 版本更新!
java·开源商城系统·tigshop
Tigshop开源商城6 小时前
『订单税率+收货地址校验国家字段』功能上新|跨境运营更高效,Tigshop开源商城系统 JAVA v5.8.23 版本更新
java·开源商城系统·tigshop
REDcker6 小时前
C++变量存储与ELF段布局详解 从const全局到rodata与nm_readelf验证实践
java·c++·面试
kobesdu8 小时前
【ROS2实战笔记-19】ROS2 生命周期节点的启动顺序、状态转换陷阱与热备方案
java·前端·笔记·机器人·ros·ros2
neo_Ggx238 小时前
Maven 版本管理详解:SNAPSHOT、Release 与 Nexus 仓库的区别和影响
java·maven
matlabgoodboy8 小时前
软件开发定制小程序APP帮代做java代码代编写C语言设计python编程
java·c语言·小程序
江离w8 小时前
新版vibecoding项目初始化指令
java
tongluowan0078 小时前
Spring MVC 底层工作流程+源码分析
java·spring·mvc
java1234_小锋9 小时前
SpringBoot为什么要禁止循环依赖?
java·数据库·spring boot
折哥的程序人生 · 物流技术专研10 小时前
《Java 100 天进阶之路》第17篇:Java常用包装类与自动装箱拆箱深入
java·开发语言·后端·面试