我认为很多时候代码写不好不是因为类不会用,而那是因为对原理的不懂,比如不学原理的话,还不知道String和StringBuffer的区别,所以我想收集一些被人忽视的忽视的细节、代码中隐患或者提高代码效率等等资料。

解决方案 »

  1.   

    servlet 尽量不要用全局变量。ps
    小弟不才前些天也发过类似的帖子。
    回帖者1人 帖子分数100
    指望楼主了
      

  2.   

    一、 避免在循环条件中使用复杂表达式
    在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。二、 避免使用NEW关键字来创建String对象
    把一个String常量copy到String 对象中通常是多余、浪费时间的。三、 在finally块中关闭Stream
    程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。四、 使用'System.arraycopy ()'代替通过来循环复制数组
    'System.arraycopy ()' 要比通过循环来复制数组快的多。五、 让访问实例内变量的getter/setter方法变成”final”
    简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载。六、 避免不需要的instanceof操作
    如果左边的对象的静态类型等于右边的,instanceof表达式返回永远为true。七、 避免不需要的造型操作
    所有的类都是直接或者间接继承自Object。同样,所有的子类也都隐含的“等于”其父类。那么,由子类造型至父类的操作就是不必要的了。八、 如果只是查找单个字符的话,用charAt()代替startsWith()
    用一个字符作为参数调用startsWith()也会工作的很好,但从性能角度上来看,调用用String API无疑是错误的!九、 使用移位操作来代替'a / b'操作
    "/"是一个很“昂贵”的操作,使用移位操作将会更快更有效。十、 使用移位操作代替'a * b'
    同上。
    [i]但我个人认为,除非是在一个非常大的循环内,性能非常重要,而且你很清楚你自己在做什么,方可使用这种方法,最好加上一些注释。否则提高性能所带来的程序晚读性的降低将是不合算的。十一、 在字符串相加的时候,使用 ' ' 代替 " ",如果该字符串只有一个字符十二、 将try/catch块移出循环
    把try/catch块放入循环体内,会极大的影响性能,如果编译JIT被关闭或者你所使用的是一个不带JIT的JVM,性能会将下降21%之多!十三、 对于boolean值,避免不必要的等式判断
    将一个boolean值与一个true比较是一个恒等操作(直接返回该boolean变量的值). 移走对于boolean的不必要操作至少会带来2个好处:
    1)代码执行的更快 (生成的字节码少了5个字节);
    2)代码也会更加干净 。十四、 对于常量字符串,用'String' 代替 'StringBuffer'
    常量字符串并不需要动态改变长度。十五、 使用条件操作符替代"if (cond) return; else return;" 结构
    条件操作符更加的简捷十六、 使用条件操作符代替"if (cond) a = b; else a = c;" 结构十七、 尽量不要在循环体中实例化变量
    在循环体中实例化临时变量将会增加内存消耗十八、 确定 StringBuffer的容量
    StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。还有什么的,大家说说啊。
      

  3.   

    举个例子常用的List遍历哈~~import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;public class Test {    public static void main(String[] args) {
            List<String> list = new ArrayList<String>();
            for (int i = 0; i < 100000; i++) {
                list.add(i + "");
            }
            long t0, t1;
            t0 = System.nanoTime();
            // ①
            t1 = System.nanoTime();
            System.out.println(t1 - t0);
        }
    }将上段程序中的①分别改成如下,可以看看执行的时间。形式一:
    for (String str : list) {
        String s = str;
    }形式二:
    for (Iterator<String> i = list.iterator(); i.hasNext();) {
        String s = i.next();
    }形式三:
    for (int i = 0; i < list.size(); i++) {
        String s = list.get(i);
    }形式四:
    for (int i = 0, k = list.size(); i < k; i++) {
        String s = list.get(i);
    }
      

  4.   

    2楼精,我收藏了,问些问题
    三、如果finally里不关闭stream,那么JAVA的垃圾回收器会自动回收么???学JAVA的时候老师就说JAVA的new并不需要delete七、什么是造型操作?八、CharAt()怎么用?为什么效率高啊?九和十、不太清楚位移操作怎么做,不过按我的理解,在一个次数很多的循环里有/,*的操作,用位移,次数很少还是直接用??十二、JIT是什么?能解释下么?
      

  5.   

    List<String> list = new ArrayList<String>();
    String s=lis.get(1);是不是比List list = new ArrayList();
    String s=(String)lis.get(1);要省时间??范式好像JDK1.5才出现,不知道具体怎么用
      

  6.   

    我只能回答您下面三个问题:三、如果不闭stream的话,很有可能你写进去的东西,在程序运行完之后有部分没有写进去,特别是写入很多东西的时候;
    八、charAt()就是取字符串中的一个字符,内部实际上已经转成了一个char数组,可以近似地认为是charAt(i)=char[i];
    九和十、这个没有一点位运算的功底,要用位运算实现乘除是没有那么简单的。PS:使用泛型肯定是要比强转快了,泛型实际上挺简单的,可以去学习一下。
      

  7.   

    3楼的我式了一下,最后一个效率最好,好像明白点了,尽量少在循环内调用函数API,最好用基础类型比较
      

  8.   

    stream不关闭的话,垃圾回收时不会回收的。stream输入IO操作,我觉得除了虚拟机外,外部的操作系统也会分配相关的资源进行处理。此外,8楼说的不是很正确。关闭流并不会强制刷新流,应该调用flush();方法将流中剩余的数据写完。
    JIT是just in time,即时编译技术。使用该技术,能够加速java程序的执行速度。
    具体可以参照http://acme1921209.javaeye.com/blog/59769
    造型操作 
    比如
     Object o = (Object)dog;         // not necessary.
    也就是强制转换,可能翻译不太一样。
      

  9.   

    按10楼所说的,connection,statement,resultset这些借助外部资源的实例用完以后也不会自动关闭,我以前想不起来写conn.close()就是认为垃圾回收器会回收它们。
    另外“流”我一直不知道其具体是个什么东西,我猜想是内存与内存外设备传输数据用的,比如写入文件,往其他计算机上传输文件,从键盘显示器接收数据,在网上看视频等等,但是内存内部一个对象从一个函数传到另一个函数就不需要流,我也不知道同样都是传输为什么会有流这个东西,这是总结一些现象罢了。
      

  10.   

    现在数据库连接都是采用连接池。如果不写conn.close()的话,connection就永远不会重新放回连接池了。
      

  11.   

    对于数据库连接池的话,conn.close()并不是真正的关闭了数据库的连接,
    一般采用动态代理重新实现了一下close()方法,只是将其还回到池中去了,
    并没有真正意义上地断开与数据库的连接。