文档章节

浅析foreach语句

o
 osc_a22drz29
发布于 2019/03/24 10:32
字数 2146
阅读 14
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

 

本篇是我对于foreach语句(增强for)的总结:

我的总结流程如下:      

                    1.先整体说明增强for遍历集合与数组之间的区别。

                    2.通过一维数组来说明(给出反编译的源码,形成对照)。

                    3.通过二维数组来说明(给出反编译的源码,形成对照)。

                    4.通过三维数组来说明(给出反编译的源码,形成对照)。

                    5.通过集合来说明(给出反编译的源码,形成对照)。

                    6.反编译的介绍以及网站分享。

                    7.结束。

一.增强for遍历集合与数组之间的区别

其实之前在我还没有学习到迭代器之前我已经总结过这个知识点了,但是在我了解过迭代器之后,我决定将之删掉重写.问过很多人,都说foreach语句无非就是一直在使用迭代器,可是在我真正测试了之后,才发现,并不像大多数人想的那样。

因为我了解到了迭代器的使用只能是在集合中(下面是API文档中的一些解释):

 

并且对之有所了解的都应该知道,迭代器只是一个接口,他的使用是要通过其实现类来完成的,而只有Collection集合或者其子类才能通过调用iterator方法返回一个实现类对象。

所以说,只有集合是通过迭代器来遍历的,但是数组就不是了,因为数组与集合并不是同一个概念。

再来说说数组与集合的不同之处吧:

                               1.集合的长度可变,而数组的长度是不可变的。

                               2.集合可以存储对象与基本类型数据,但是数组只能存储基本类型数据。

二.通过一维数组来说明

  普通代码:

public class Demo9 {
    public static void main(String[] args) {
        int[] a= {1,2,3,4,4,5};
        for(int i:a) {
            System.out.println(i);
    }
}
}

反编译后的代码:

public class Demo10 {

   public static void main(String[] args) {
      int[] a = new int[]{1, 2, 3, 4, 4, 5};           //按照计算机的创建数组的标准格式创建一个数组
      int[] var5 = a;                                                 //相当于复制a数组
      int var4 = a.length;                                           //记录a数组的长度
      for(int var3 = 0; var3 < var4; ++var3) {
         int i = var5[var3];                                       //将a数组元素逐个赋值给i
         System.out.println(i);
      }

   }
}

通过反编译代码,很明显可以看到,对于数组使用增强for与迭代器是没有任何关系的(这篇就翻过啦,哈哈),我把解释全部写在反编译的代码中了。

三.通过二维数组来说明(这将是我说明的重点)

普通代码:

public class Demo6 {
    public static void main(String[] args) {
              int[][]  a= {{1,2,3},{2,5,3}};
              for(int i[]:a) {         //此处用了两次foreach语句,具体原因我们通过反编译代码说明
                  for(int e:i) {
                      System.out.println(e);
                  }
              }
              System.out.println(a.length);
    }
}

反编译代码:

public class Demo5 {

 public static void main(String[] args) {
  int[][] a = new int[][]{{1, 2, 3}, {2, 5, 3}};                   //这里仍是一个标准的二维数组创建格式
  int[][] var5 = a;                                               //又复制了一遍数组
  int var4 = a.length;                                          //把a的长度2给了var4
  for(int var3 = 0; var3 < var4; ++var3) {                  //这个循环进行两次
  int[] i =var5[var3];                   //此处是我理解的一个困难之处,但是我已克服,会在下面说出我的见解           
int[] var9 = i; //又复制了一次数组 int var8 = i.length; //给长度 for(int var7 = 0; var7 < var8; ++var7) { int e = var9[var7]; //这里就和一维数组完全一样了 System.out.println(e); } } } }

我会通过语言描述,将我所理解到的,二维数组的foreach遍历中的我之前不理解但现在已解决的地方说出来:

             int[] i =var5[var3];
             int[] var9 = i;
i.length=3;
i数组输出出来是二维数组中的一维数组(就是每一个大括号中的内容)

此处最初令我十分不解。因为我大一上学期是学c语言的,在我的脑海中数组这些知识都应该是通用的,但是我却没见过这种方式,在我最初的理解中,我之所以遇到困难,是因为我一直纠结于将一个地址直接给一个数组是不合适的,但是我后来又试了一下,发现如果我们将代码写成这样就很好理解了。

             int[] i =new int[5];
             i=var5[var3];

因为我想通过这样的方式来帮助我理解的话,我事先必须先定义一个数组,出于尝试的态度,我将它的初始长度设为5,但上文代码中,我们知道最后i的长度是3,最先我以为这里的i是被覆盖了,后来才发现并不是这样,因为var5[var3]是二位数组的行的首地址,所以只是改变了i的指向,他所指向的变成了a数组的每一行的行首,所以他就相当于,通过遍历,不断地复制二维数组每一行的元素。

当然有人会问了,你怎么去确定,他的长度为啥就一定是与二维数组第一行长度一样?

其实,我们会发现在二维数组中,每一行的首地址都是不一样的,我所谓的不一样是没有规律的,就是他们并不是整个二维数组连在一起的,而是以行为单位的连在一起的。

四.通过三维数组说明问题

普通代码:

public class Demo10 {
    public static void main(String[] args) {
           int[][][]  a= {{{1,2,3},{2,3}},{{2,3},{2,6}},{{3,4},{5,6}}};
           for(int[][] b:a) {
               for(int[] c:b) {
                   for(int d:c) {
                       System.out.println(d);
                   }
               }
           }
    }

}

此处我决定只是通过普通代码的方式来说明问题,因为计算机总是会自己创造出一些变量,对于三维数组来说,这些变量就更多了(看看二维数组,唉。。),这样只会是我们的理解更加的不具体,不直观。

其实我们不难发现,无论多高维度的数组,将其输出的格式都是一样的,最终的输出语句一定是在一维数组中的。

五.通过集合说明

普通代码:

import java.util.ArrayList;
import java.util.Collection;

public class Demo8 {
  public static void main(String[] args) {
       Collection  cc=new ArrayList();
       cc.add("哈哈");
       cc.add("嘻嘻");
       cc.add("哼哼");
       cc.add(1);
       for(Object s:cc) {
           System.out.println(s);
       }
}
}

反编译代码:

import java.util.ArrayList;
import java.util.Iterator;

public class Demo8 {

   public static void main(String[] args) {
      ArrayList cc = new ArrayList();
      cc.add("鍝堝搱");                                      //这里的字符串应该只是机器码的缘故,我并没有深究
      cc.add("鍢诲樆");
      cc.add("鍝煎摷");
      cc.add(Integer.valueOf(1));
      Iterator var3 = cc.iterator();

      while(var3.hasNext()) {
         Object s = var3.next();
         System.out.println(s);
      }

   }
}

很明显这次我们发现,用增强for遍历集合反编译的格式完全不一样了,并且还用到了迭代器,并且我并没有使用泛型,即没有给出数据类型,这样也更好理解一些。

对于其中的一些关于集合的知识,比如说迭代器的相关方法呀,之类的我就不在本篇说啦,对于集合我还是会总结的。

六.反编译的使用

何为反编译,我的理解就是将那些隐藏句式的全部代码显现出来,对于foreach语句的理解若是没有反编译我是绝对不可能做出来的,最初的时候,我试着用javap进行反汇编但是我发现里面的东西并不是我想看到的,所以我花了一个小时,去找那种我想要的反编译软件,最后发现不是安装太麻烦,就是不适合我。。。。。。。。。

好在偶然发现了一个网站,很好使,完全就是用来进行我所需要的那种反编译的,所以如果看我的文章还是不太理解的话,可以在评论区与我进行讨论,或者通过这个网站形成你自己的理解,网址在这了(http://javare.cn/)。

七.结束

其实之前,我已经总结过该知识点了,并且看的人还挺多的,那时我也是初学,没有思考的太过深入,所以就按照自己所想总结了一下,但是昨天翻看的时候发现总结的那叫一个惨不忍睹,一点逻辑性都没有,这样其实对于那些耐着性子,看我这个菜鸟的博客的人挺不好的,所以我就删掉决定重写,我并不能保证该篇中就没有一点问题,但是这绝对是我深思熟虑的结果。还是老样子,加油,慢慢变强吧。

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Swift百万线程攻破单例(Singleton)模式

一、不安全的单例实现 在上一篇文章我们给出了单例的设计模式,直接给出了线程安全的实现方法。单例的实现有多种方法,如下面: class SwiftSingleton { } 这段代码的实现,在shared中进行条...

一叶博客
2014/06/20
3.6K
16
Java™ 编译器--Janino

Janino是一个超级小但又超级快的Java™ 编译器. 它不仅能像javac工具那样讲一组源文件编译成字节码文件,还可以对一些Java表达式,代码块,类中的文本(class body)或者内存中源文件进行编译,...

匿名
2013/04/02
4.2K
0
Akka实战:分散、聚合模式

分散与聚合:简单说就是一个任务需要拆分成多个小任务,每个小任务执行完后再把结果聚合在一起返回。 代码 http://git.oschina.net/yangbajing/akka-action 实例背景 本实例来自一个真实的线...

羊八井
2015/11/26
3.7K
13
Spark数据挖掘-深入GraphX(1)

Spark数据挖掘-深入GraphX(1) 1 网络数据集 当图被用来描述系统中的组件之间的交互关系的时候,图可以被用来表示任何系统。图原理提供了通用的语言和一系列工具来表示和分析复杂的系统。简单...

clebeg
2015/11/26
970
2
Android Studio for Experts(Android Dev Summit2015)

按照规矩,先贴参考来源: 来自简书的iamwent的Android Studio for Experts:Edit(很多帮助,多谢!) Android Studio Tips and Tricks Android Studio Tips & Tricks: Moving Around(这篇文章...

李琦
2015/11/29
1.4K
1

没有更多内容

加载失败,请刷新页面

加载更多

【实用技巧】MAC苹果电脑怎么远程?

一般电脑远程包括三方面: 1、如果从外部windows或者linux终端连接到mac苹果电脑; 2、从苹果电脑内如何远程外面的windows、linux和mac等; 3、苹果和安卓手机怎么远程连接苹果/Windows电脑。...

osc_doeya1ck
12分钟前
0
0
虚拟主机和VPS主机有哪些不同点呢

虚拟主机是一种在单一主机或主机群上,实现多网域服务的方法,可以运行多个网站或服务的技术。vps主机是将一台服务器分割成多个虚拟专享服务器的服务。实现VPS的技术分为容器技术和虚拟机技术...

osc_b88oux8w
13分钟前
0
0
合理的使用MySQL乐观锁与悲观锁

针对 MySQL的乐观锁与悲观锁的使用,基本都是按照业务场景针对性使用的。针对每个业务场景,对应的使用锁。 但是两种锁无非都是解决并发所产生的问题。下面我们来看看如何合理的使用乐观锁与...

php开源社区
14分钟前
0
0
fusionpbx 中文 汉化

  自己以前有从事过呼叫中心的工作经验,然而由于自己是从事后端开发,对于前端界面的开发还是有些吃力,但是自己却又想自己搭建一套呼叫中心,所以购买了一台云服务器并克隆了FusionPBX的...

osc_ydeb2o99
15分钟前
7
0
关于大O表示法和小O表示法

上节课老师讲了一下各种表示法,当时没咋听懂,后来查了一些资料弄懂了,记录一下。 主要是从维基百科上看的。http://en.wikipedia.org/wiki/Big_O_notation 大O表示法: f(x) = O(g(x)) 表示...

osc_3mzamgkq
16分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部