淺析foreach語句


 

本篇是我對於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/)。

七.結束

其實之前,我已經總結過該知識點了,並且看的人還挺多的,那時我也是初學,沒有思考的太過深入,所以就按照自己所想總結了一下,但是昨天翻看的時候發現總結的那叫一個慘不忍睹,一點邏輯性都沒有,這樣其實對於那些耐着性子,看我這個菜鳥的博客的人挺不好的,所以我就刪掉決定重寫,我並不能保證該篇中就沒有一點問題,但是這絕對是我深思熟慮的結果。還是老樣子,加油,慢慢變強吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM