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

坦白讲身为程序员,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个整数,没有重新生成。

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

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

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

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

foreach写失效的问题的更多相关文章

  1. 【Java学习笔记之十】Java中循环语句foreach使用总结及foreach写法失效的问题

    foreach语句使用总结 增强for(part1:part2){part3}; part2中是一个数组对象,或者是带有泛性的集合. part1定义了一个局部变量,这个局部变量的类型与part2中的对 ...

  2. mybatis的foreach写用法

    一.mybatis查询 public abstract List<Model> findByIds(@Param("ids")List<Integer> i ...

  3. 20162330 第三周 蓝墨云班课 泛型类-Bag 练习

    目录 题目及要求 思路分析 遇到的问题和解决过程 代码实现及托管链接 感想 参考资料 题目及要求 代码运行在命令行中,路径要体现学号信息,IDEA中,伪代码要体现个人学号信息: 参见Bag的UML图, ...

  4. cache写策略

    cache写策略 Write Through (完全写入) CPU向cache写入数据时,同时向memory也写一份,使cache和memory的数据保持一致.优点是简单,缺点是每次都要访问memor ...

  5. EffectiveC#11--选择foreach循环

    1.C#的foreach语句可以为你的任何集合产生最好的迭代代码 不推荐如下写法(?原因未明白 作者意思是阻碍jit边界检测) int len = foo.Length; for ( int inde ...

  6. innodb 关键特性(两次写与自适应哈希索引)

    两次写: 场景: 当发生数据库宕机时,可能innodb存储引擎正在写入某个页到表中,而这个页只写了一部分,这种情况被称为部分写失效,如果发生,可以通过重做日志进行恢复,重做日志中记录的是对页的物理操作 ...

  7. MySQL InnoDB特性:两次写(Double Write)

    http://www.ywnds.com/?p=8334 一.经典Partial page write问题? 介绍double write之前我们有必要了解partial page write(部分页 ...

  8. InnoDB的关键特性-插入缓存,两次写,自适应hash索引

    InnoDB存储引擎的关键特性包括插入缓冲.两次写(double write).自适应哈希索引(adaptive hash index).这些特性为InnoDB存储引擎带来了更好的性能和更高的可靠性. ...

  9. java 中,for、for-each、iterator 区别

    java 中,for.for-each.iterator 区别: 无论是在数组中还是在集合中,for-Each加强型for循环都是它们各自的普通for循环的一种"简写方式",即两者 ...

随机推荐

  1. 排序矩阵中的从小到大第k个数 · Kth Smallest Number In Sorted Matrix

    [抄题]: 在一个排序矩阵中找从小到大的第 k 个整数. 排序矩阵的定义为:每一行递增,每一列也递增. [思维问题]: 不知道应该怎么加,因为不是一维单调的. [一句话思路]: 周围两个数给x或y挪一 ...

  2. workerman使用

    1.start_timer.php(boc) <?php use \Workerman\Worker; use \Workerman\Lib\Timer; require_once '/var/ ...

  3. [BAT]操作系统定时任务调用批处理忽略error继续运行的方法

    如下,通过forfiles删除7天以前生成的一些文件,当不存在满足搜索条件的文件时,就会报错:ERROR: No files found with the specified search crite ...

  4. maven 编译的时候总是报一些奇怪的错误 比如 surefire-boot 2.10 .jar 可是私服里查看本来就没有这个高的版本。

    或者私服总是 报 read time out , 或者  io 错误,  或者 gzip 解压错误,或者总是尝试下载一些高版本的jar , 而这些jar 可能是不存在的 .. 尝试 重新下载 apac ...

  5. Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.

    解决方法: <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-m ...

  6. 2018.08.22 codves2370 小机房的树(lca+树上差分)

    传送门 一道板子题. 直接树链剖分维护树上lca然后差分就行了. 代码: #include<bits/stdc++.h> #define N 50005 #define lc (p< ...

  7. HDU 2504 又见GCD (最大公因数+暴力)

    题意:是中文题. 析:a和c的最大公因数是b,也就是说,a和c除了b就没有公因数了.再说就是互质了. 所以先把a除以b,然后一个暴力n,满足gcd(a, n) =1,就结束,就是n倍的c. 代码如下: ...

  8. HDU 1718 Rank (排序)

    题意:给你n个学号和成绩,并且给定一个学号,让找这个学号是多少名. 析:用个结构体,按成绩排序,然后找那个学号,这个题有一个小坑,那就是并列的情况, 可能并列多少名,这个要考虑一下,其他的easy! ...

  9. Android线程和线程Handler基础一览

    线程概览 线程是任何多任务系统的基石.可以被认为是一个主进程的多个子进程.这样做的目的就是了增加应用的性能. 应用主线程 当一个Android应用被打开的时候,系统会默认开辟一个线程.这个线程就被叫做 ...

  10. Watermelon -- codeforces

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=93241#problem/A  (654123) http://codeforces.co ...