使用foreach需要判空。


今天寫代碼的時候,需要遍歷一個作為參數傳遞進來的容器,

當時順手就加上了判空條件:

if(null==list)return;

后來就像,不知道遍歷(foreach)有沒有幫我做這個工作:

下面看實驗結果:

public static void main(String[] args) {
        List<String> list =null;
        for (String s:list){
            System.out.println(s);
        }
    }

運行時報空指針錯誤:

Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:37)

說明在進行foreach遍歷的時候,需要判空的。

下面看看foreach到底是怎么實現的:

foreach是在jdk 1.5版本后推出更優雅的遍歷寫法:

jdk1.5之前:

遍歷數組:

1  for (int i=0;i<array.length;i++){
2    //do something
3 }

遍歷容器:

while (list.iterator().hasNext()){
            //do something
        }

jdk1.5之后:

 for (String s:list){
           //do something
        }

代碼看起來優雅了許多。

那foreach是一個新的東西么?相對於以前的的for循環來說,到底哪個效率要高一些呢?

下面看測試代碼:

    List<String> list = new ArrayList<>();
    String[] test = new String[]{};

    //遍歷容器測試
    public void collectionForeachTest() {
        for (String s : list) {
            //do something
        }
    }

    //循環容器測試
    public void collectionIteatorTest() {
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            //do something
        }
    }

    //遍歷數組測試
    public void arrayForeachTest() {
        for (String s : test) {
            //do something  
        }
    }

    //循環數組測試
    public void indexTest() {
        for (int i = 0; i < test.length; i++) {
            //do something
        }
    }

首先編譯。javap -c Test.class查看編譯源文件:

容器:使用遍歷和迭代器:

public void collectionForeachTest();
    Code:
       0: aload_0
       1: getfield      #4                  // Field list:Ljava/util/List;
       4: invokeinterface #7,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
       9: astore_1
      10: aload_1
      11: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
      16: ifeq          32
      19: aload_1
      20: invokeinterface #9,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      25: checkcast     #5                  // class java/lang/String
      28: astore_2
      29: goto          10
      32: return

  public void collectionIteatorTest();
    Code:
       0: aload_0
       1: getfield      #4                  // Field list:Ljava/util/List;
       4: invokeinterface #7,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
       9: astore_1
      10: aload_1
      11: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
      16: ifeq          22
      19: goto          10
      22: return

數組:遍歷和索引:

 public void arrayForeachTest();
    Code:
       0: aload_0
       1: getfield      #6                  // Field test:[Ljava/lang/String;
       4: astore_1
       5: aload_1
       6: arraylength
       7: istore_2
       8: iconst_0
       9: istore_3
      10: iload_3
      11: iload_2
      12: if_icmpge     26
      15: aload_1
      16: iload_3
      17: aaload
      18: astore        4
      20: iinc          3, 1
      23: goto          10
      26: return

  public void indexTest();
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: aload_0
       4: getfield      #6                  // Field test:[Ljava/lang/String;
       7: arraylength
       8: if_icmpge     17
      11: iinc          1, 1
      14: goto          2
      17: return

 

可以看出來,總體來說:foreach就是iterator的語法糖,使用foreach,最后都會編譯成傳統的Iterator的方法。

結論:

1.使用foreach需要檢查對象是否為空,因為使用foreach相當於使用了obj.itreator()

2.foreach只是一個語法糖,使用foreach更安全(不會帶來數組越界的錯誤),但是最終編譯結果和以前的寫法是一樣的。

 


免責聲明!

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



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