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个整数,没有重新生成。


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



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

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


相关文章:
【推荐】 Spring-Boot自定义Starter实践
【推荐】 Android事件分发机制浅析(3)
【推荐】 云捕Redis实战