• 使用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更安全(不会带来数组越界的错误),但是最终编译结果和以前的写法是一样的。

  • 相关阅读:
    Http服务器实现文件上传与下载(二)
    Http服务器实现文件上传与下载(三)
    NHibernate VS IbatisNet
    5. Element-UI的基本使用
    4. Vue脚手架
    3. Vue单文件组件
    webpack中的加载器
    webpack
    02.模块化相关规范
    01.前端工程化的学习目标
  • 原文地址:https://www.cnblogs.com/dengchengchao/p/8833049.html
Copyright © 2020-2023  润新知