Java代码优化技巧分享(一)

前言:

优化代码,使自己的代码精,简,灵活,效率高。(高扩展、高内聚、低耦合)。日常细节必不可少。最好的比喻“滴水穿石”。要知道一个个细小的优化点累积起来,对于代码的运行效率绝对是有提升的。反之。一个个的堆积。将会最终到一个系统的崩溃。此话一点也不夸张。

1、及时关闭流
原因:重复流 占用 ! 资源得不到释放。。 造成大量的内存垃圾等问题
2、尽量重用对象
比如说字符串连接时。应该用StringBuilder/StringBuffer代替。原因:String对象一旦创建对象不可变。用StringBuilder/StringBuffer对象可变。所以少了创建和回收。效率上自然高于String。
3、尽量减少对变量的重复计算

for (int i = 0; i < list.size(); i++)
建议替换为:
for (int i = 0, int length = list.size(); i < length; i++)

原因:list.size()越大消耗内存越大。
4、尽量采用懒加载的策略,即在需要的时候才创建

String str = “aaa”;
if (i == 1) {
    list.add(str);
}
建议替换为:
if (i == 1) {
    String str = “aaa”;
    list.add(str);
} 

原因:一个是不管用不用就创建和用到再创建。效率上很容易比对。
5、慎用异常
异常对性能不利。抛出异常首先要创建一个新的对象,Throwable接口的构造函数调用名为fillInStackTrace()的本地同步方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,Java虚拟机就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。异常只能用于错误处理,不应该用来控制程序流程。
6、使用try…catch…,尽量放在最外层
原因:把try…catch…放在循环外面。遇到异常就直接跳出了循环。放在里面会继续执行。具体情况还需根据情况而定。举例:如果是一个服务器线程维持一直处理其它线程产生的数据,为了保证系统的稳定性,就必须放在里面的方式来执行编码。
7、当复制大量数据时,使用System.arraycopy()命令
8、乘法和除法使用移位操作

for (val = 0; val < 100000; val += 5){
    a = val * 8;
    b = val / 2;
} 
用移位操作可以极大地提高性能,因为在计算机底层,对位的操作是最方便、最快的,因此建议修改为:
for (val = 0; val < 100000; val += 5){
    a = val << 3;
    b = val >> 1;
} 

移位操作虽然快,但是可能会使代码不太好理解,因此最好加上相应的注释。
9、循环内不要不断创建对象引用

for (int i = 1; i <= count; i++){
    Object obj = new Object();
} 
这种做法会导致内存中有count份Object对象引用存在,count很大的话,就耗费内存了,建议为改为:
Object obj = null;
for (int i = 0; i <= count; i++) { 
    obj = new Object();
} 

这样的话,内存中只有一份Object对象引用,每次new Object()的时候,Object对象引用指向不同的Object罢了,但是内存中只有一份,这样就大大节省了内存空间了。
10、基于效率和类型检查的考虑,应该尽可能使用array,无法确定数组大小时才使用ArrayList
11、尽量使用HashMap、ArrayList、StringBuilder,除非线程安全需要,否则不推荐使用Hashtable、Vector、StringBuffer,后三者由于使用同步机制而导致了性能开销
12、不要将数组声明为public static final
因为这毫无意义,这样只是定义了引用为static final,数组的内容还是可以随意改变的,将数组声明为public更是一个安全漏洞,这意味着这个数组可以被外部类所改变
13、及时清除不再需要的会话
14、尽量避免随意使用静态变量
要知道,当某个对象被定义为static的变量所引用,那么gc通常是不会回收这个对象所占有的堆内存的,如:

public class A {
    private static B b = new B();
} 

此时静态变量b的生命周期与A类相同,如果A类不被卸载,那么引用B指向的B对象会常驻内存,直到程序终止
15、尽量在合适的场合使用单例
使用单例可以减轻加载的负担、缩短加载的时间、提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:

(1)控制资源的使用,通过线程同步来控制资源的并发访问

(2)控制实例的产生,以达到节约资源的目的

(3)控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信
16、使用数据库连接池和线程池
这两个池都是用于重用对象的,前者可以避免频繁地打开和关闭连接,后者可以避免频繁地创建和销毁线程
17、使用同步代码块替代同步方法
这点在多线程模块中的synchronized锁方法块一文中已经讲得很清楚了,除非能确定一整个方法都是需要进行同步的,否则尽量使用同步代码块,避免对那些不需要进行同步的代码也进行了同步,影响了代码执行效率。
18、不要让public方法中有太多的形参
public方法即对外提供的方法,如果给这些方法太多形参的话主要有两点坏处:
① 违反了面向对象的编程思想,Java讲求一切都是对象,太多的形参,和面向对象的编程思想并不契合
② 参数太多势必导致方法调用的出错概率增加
至于这个”太多”指的是多少个,3、4个吧。比如我们用JDBC写一个insertStudentInfo方法,有10个学生信息字段要插如Student表中,可以把这10个参数封装在一个实体类中,作为insert方法的形参。
19、公用的集合类中不使用的数据一定要及时remove掉
如果一个集合类是公用的(也就是说不是方法里面的属性),那么这个集合里面的元素是不会自动释放的,因为始终有引用指向它们。所以,如果公用集合里面的某些数据不使用而不去remove掉它们,那么将会造成这个公用集合不断增大,使得系统有内存泄露的隐患。
20、 在JAVA + ORACLE 的应用系统开发中,java中内嵌的SQL语句尽量使用大写的形式,以减轻ORACLE解析器的解析负担。
21、不用new关键词创建类的实例
用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的 clone()方法。clone()方法不会调用任何类构造函数。
22、使用’system.arraycopy ()’代替通过来循环复制数组

例子:

public class irb
{
    void method () {
        int[] array1 = new int [100];
        for (int i = 0; i < array1.length; i++) {
            array1 [i] = i;
        }
        int[] array2 = new int [100];
        for (int i = 0; i < array2.length; i++) {
            array2 [i] = array1 [i];                 // violation
        }
    }
}

更正:

public class irb
{
    void method () {
        int[] array1 = new int [100];
        for (int i = 0; i < array1.length; i++) {
            array1 [i] = i;
        }
        int[] array2 = new int [100];
        system.arraycopy(array1, 0, array2, 0, 100);
    }
}

23、二维数组比一维数组占用更多的内存空间,大概是10倍计算。
24、避免枚举,浮点数的使用。
25、用switch-case替代冗长的if-else-if

猜你喜欢

转载自blog.csdn.net/qq_23303245/article/details/80743748