• foreach写失效的问题


    本文由作者张远道授权网易云社区发布。


    坦白讲身为程序员,bug在所难免。有人讲,bug越多,说明程序员越伟大。这句话有它一定的道理。

    因为从某方面讲,bug多了说明他的代码量也多。

    言归正传,这里我记录了我曾经犯过的几个错误。希望看到的同侪能够见而避之。

    常用的一个场景,遍历一个集合,对符合某种条件的元素做修改。习惯性地会写出如下代码:

     


         List testInt = new ArrayList();
         testInt.add(1);
         testInt.add(2);
         testInt.add(3);     for(Integer temp :testInt ){      if(temp==1)
             temp=temp*2;
         }   
         for(Integer a:testInt ){
          System.err.println(a);
         }




    期待的结果是:

    2

    2

    3

    但实际输出为:

    1

    2

    3


    这是很容易掉进去的陷阱。即通过foreach遍历对集合元素进行修改。在以为变更已发生的时候,

    其实变更没有发生。造成数据写入失败。


    因为



        for(Integer temp:testInt){     if(temp==1)
            temp=temp*2;
        }



    将被翻译成

        for(int i=0,length=testStr.size();i<length;i++){

            Integer temp = testStr.get(i).clone();

            if(temp==1)

            temp=temp*2;

        }


    根据oracle的官方文档,正式翻译应该如下


    	    for (Iteratori = testInt.iterator(); i.hasNext(); ) {	        float i0 = (Integer)i.next();	        if(i0 == 1)
    	        	i0 = i0*2;
    	    }



    即,foreach里头的的 temp变量只是一个局部变量,而且还是集合中元素的一个副本,并不是元素本身。


    想到之前还遇到的一个问题,代码简化如下:


    	Integer integer1 = 3;
    		Integer integer2 = 3;		if (integer1 == integer2)
    			System.out.println("integer1 == integer2");		else
    			System.out.println("integer1 != integer2");
    
    		Integer integer3 = 300;
    		Integer integer4 = 300;		
    		if (integer3 == integer4)
    			System.out.println("integer3 == integer4");		else
    			System.out.println("integer3 != integer4");


    即在判断整数相等时,使用了封装类(由数据库映射过来,用封装类防止反射异常)。实际的输出结果如下:

    integer1 == integer2

    integer3 != integer4

    明眼人很容易看出来,这里掉入了两个坑.一个坑是用等号判断相等,除非是为了比较同一个对象,等值比较不应该直接用等号。 另一个坑是

    java的整数缓存。

    查看jdk的源码如下:

        


    private static class IntegerCache {        static final int low = -128;        static final int high;        static final Integer cache[];        static {            // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");            if (integerCacheHighPropValue != null) {                int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);                // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low));
                }
                high = h;
    
                cache = new Integer[(high - low) + 1];            int j = low;            for(int k = 0; k < cache.length; k++)
                    cache[k] = new Integer(j++);
            }        private IntegerCache() {}
        }



    即整数缓存缓存了前127个整数,没有重新生成。


    当然,还遇到其它各种各样的坑。可怕的不是掉入坑中,而是掉入坑里了不正视问题也不查找问题所在,一而再再而三地掉进坑里。



    免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

    更多网易技术、产品、运营经验分享请访问网易云社区


    相关文章:
    【推荐】 从加班论客户端开发中的建模

  • 相关阅读:
    近期安卓与IOS招聘面试有感
    java线程池技术(二): 核心ThreadPoolExecutor介绍
    java线程池技术(一):ThreadFactory与BlockingQueue
    Java设计模式之策略模式与状态模式
    java线程间通信:一个小Demo完全搞懂
    Android M 新的运行时权限开发者需要知道的一切
    Java多线程同步问题:一个小Demo完全搞懂
    java多线程之守护线程以及Join方法
    安卓电量优化之JobScheduler使用介绍
    安卓电量优化之WakeLock锁机制全面解析
  • 原文地址:https://www.cnblogs.com/163yun/p/10118445.html
Copyright © 2020-2023  润新知