首页 > 编程语言 >一个Java增强型for循环的易犯错误,你注意到了吗?

一个Java增强型for循环的易犯错误,你注意到了吗?

时间:2022-12-17 10:05:03浏览次数:60  
标签:Java 增强型 代码 元素 修改 循环 易犯 数组


我们知道,在Java语言中有三种循环,分别是while循环,do…while循环和for循环。其实,从JDK1.5开始,又引入了一种增强型for循环,这种新型的for循环主要是用来遍历数组或集合的,它的格式非常简单,下图展示了增强型for循环的基本结构:

一个Java增强型for循环的易犯错误,你注意到了吗?_数组元素

增强型for循环被设计出来就是为了遍历数组或者是集合的,所以在循环中都会指定一个数组或者是集合。为了方便程序员编码,增强型for循环不再通过”下标”的形式访问数组或集合中的元素,而是把依次从数组或集合取出元素,并命名为i,这样,程序员就可以直接操作元素i,从而大大简化了代码。为了方便表述,我们把元素i称之为“当前元素”。下面来看一个简单例子:

一个Java增强型for循环的易犯错误,你注意到了吗?_数组元素_02

在这个增强型for循环中,指定的数组叫做array。每次循环,都从array数组中取出一个元素并命名为i,之后打印元素i的值。这里特意提醒各位小伙伴一下:循环中出现的”i”并非数组的下标,而是一个数组元素,也就是我们前面所说的”当前元素“。这段程序运行结果是”1 2 3 “。如果使用传统的for循环也能达到同样的效果,代码如下:

一个Java增强型for循环的易犯错误,你注意到了吗?_数组_03

仅从以上两段代码的运行结果来看,似乎增强型for循环和传统for循环没有什么区别。但是,如果把以上两段代码稍作修改,运行结果就会迥然不同。我们把第一段代码改为如下形式:

一个Java增强型for循环的易犯错误,你注意到了吗?_java_04

为了表述方便,我们把第一段修改后的代码称之为”代码①”。之后,把原来的第二段代码修改为以下形式:

一个Java增强型for循环的易犯错误,你注意到了吗?_数组_05

同理,我们把修改后的第二段代码称为”代码②”。”代码①”和”代码②”都是在它们原来的版本基础之上添加了一段循环修改数组元素值的操作。

但是,再次运行程序就会发现,”代码①”的运行结果仍然是”1 2 3 ”,而”代码②”的运行结果是”3 4 5 ”,也就是说”代码①”中修改数组元素值的操作并没有起作用。这是为什么呢?就是因为:”代码①”中所谓的”当前元素”i其实是一个作用域仅限于循环自身的局部变量,每次循环开始的时候都要重新定义这个变量,并且重新用数组元素对变量i进行赋值。i的值来源于数组元素,但i本质上并不是数组元素本身,它只是数组元素的副本,因此修改i并不能改变数组元素的值。在”代码①”的第一个循环中,修改的就是局部变量i的值,而并非数组元素本身的值。因此,在”代码①”的第二个循环中打印”当前元素”,实际上是再次把数组元素的值赋值给局部变量i并且打印,既然数组元素的值并未改变,打印出的结果当然是原数组中的”1 2 3”。

再来看”代码②”,”代码②”中的第一个循环是通过下标的直接找到了真实的数组元素并且做了修改,每次操作都修改的是实实在在的数组元素,而不是数组元素的副本!所以程序运行到第二个循环中,打印的是修改后的数组元素。

以上讲解,就是为了让小伙伴们明白:增强型for循环中的那个”当前元素i”,其实是一个临时的局部变量,它只是数组元素的副本,而非数组元素本身。但是,我们所举的例子中,数组的类型属于基础数据类型。那么,如果数组并非基础类型,而是引用类型,使用增强型for循环能否修改数组元素呢?请看以下代码:

一个Java增强型for循环的易犯错误,你注意到了吗?_增强型for循环_06

在这段代码中,首先定义了一个Num类,在Num类中有一个int型的属性x,我们通过构造方法初始化x的值。代码的Test类中,在主方法里定义了一个Num类型的数组array,这个数组显然是一个引用类型数据的数组。数组中的引用分别指向了3个Num类型的对象,这三个对象的x属性值分别是1,2,3。第一个for循环修改了数组中每个Num对象的x属性值,第二个循环依次打印出每个Num对象的x属性值,程序运行结果是在控制台上输出了”3 4 5”。这说明增强型for循环在遍历引用类型的数组时,通过”当前元素”可以修改数组中元素的状态,这又是为什么呢?原因其实也很简单,虽然”当前元素”n本质上也只是一个作用域仅限于循环内部的局部引用,但是,每次循环过程中,它都实实在在的指向了一个真实的数组元素,所以这个局部引用作用域虽小,但通过它却能够完成修改数组元素对象属性值的操作。

另外再强调一点,无论增强型for循环所遍历的是基础数据类型的数组,还是引用类型的数组(或集合),都要保证”当前元素”与数组中真实元素的“类型兼容性”,否则程序就会报错。比如说,我们通过一个增强型for循环操作一个int型数组时,可以把”当前元素”i设定为double类型,原因就是数组中int型的元素可以赋值给double类型的局部变量。但反过来,通过增强型for循环操作一个double型数组时,不能把”当前元素”i的类型设定为int类型,就是因为按照Java语法,无法完成由double到int的自动转换。同理,操作一个String型数组时,可以把”当前元素”的类型设定为Object,反之则无法通过编译。

希望通过这篇文章能够让小伙伴们能更深入了解Java增强型for循环的本质。

​本专栏每篇文章讲解一个知识点,如果想系统学习Java编程可以点击这里观看我在本站的视频课程,也可以订阅我的免费专栏《Java从小白到高手》。

标签:Java,增强型,代码,元素,修改,循环,易犯,数组
From: https://blog.51cto.com/u_2266836/5949445

相关文章

  • Java千问:Java语言各种数字的“非常规”写法你都会吗?
    Java程序中总是会出现一些数字。我们通常都是用常规的方式来表示这些数字,如以下代码所示inta=1;doubleb=1.5;但是数字也可以有非常规写法,在这里我们用一篇短文简单总......
  • Java数组(05)多维数组
          ......
  • java项目启动动画
    http://patorjk.com/software/taag/#p=testall&f=Graffiti&t=study......
  • 【Java】单号创建服务
     需求:ERP项目存在若干个业务功能,每个业务的单子的单号创建规则需要被统一规划1、每个业务有自己对应的标识2、业务单号必须以英文字母为前缀,长度在2-4个字符3、单号......
  • JAVA学习日记--Scanner类
     1。导包import包路径.类名称;如果需要使用的目标类,和当前类位于同一个包下。则可以省略导包语句不写。只有java.Lang包下的内容不需要导包,其他的包都需要import语句。2......
  • 【java-02】Nginx以及前后端分离项目在linux上的部署
    目录写在开头Nginx重点目录/文件配置文件结构server块反向代理负载均衡写在开头本篇主要介绍了nginx的简单使用,包括目录结构、配置文件结构、反向代理和负载均衡等。以及......
  • Java亿级项目架构设计与落地应用 学习计划 最后附上下载地址
    Java亿级项目架构设计与落地应用 学习计划最后附上下载地址从分析应用到实际落地,完成支撑高并发读(60万/秒)的架构方案。学习架构演变的过程,同时将核心功能应用向服务器进......
  • Javascript | 分别用async await异步方法和Promise来实现一个简易的求职程序
     关注公众号,一起交流,微信搜一搜:LiOnTalKING JavaScriptPromisePromise是一个ECMAScript6提供的类,目的是更加优雅地书写复杂的异步任务。如何创建一个Pro......
  • JAVA并发-Disruptor框架
    JAVA并发-Disruptor框架Disruptor简介最好的方法去理解Disruptor就是将它和容易理解并且相似的队列,例如BlockingQueue。Disruptor其实就像一个队列一样,用于在不同的线程......
  • Java虚拟机定义
    虚拟机是一种抽象化的​​计算机​​​,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的​​​硬体​​​架构,如​​​处理器​​......