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

相关推荐
智慧老师2 分钟前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm4 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
yngsqq29 分钟前
一键打断线(根据相交点打断)——CAD c# 二次开发
windows·microsoft·c#
V+zmm1013437 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
咸鱼桨2 小时前
《庐山派从入门到...》PWM板载蜂鸣器
人工智能·windows·python·k230·庐山派
J不A秃V头A2 小时前
IntelliJ IDEA中设置激活的profile
java·intellij-idea
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode