Java程序性能优化

Java程序性能优化

关键字: java 性能

一、避免在循环条件中使用复杂表达式


在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。

例子:

Java代码

  1. import java.util.Vector;   
  2. class CEL {   
  3.     void method (Vector vector) {   
  4.         for (int i = 0; i < vector.size (); i++)  // Violation   
  5.             ; // ...   
  6.     }   
  7. }  

import java.util.Vector;

class CEL {

    void method (Vector vector) {

        for (int i = 0; i < vector.size (); i++)  // Violation

            ; // ...

    }

}

 



更正:

Java代码

  1. class CEL_fixed {   
  2.     void method (Vector vector) {   
  3.         int size = vector.size ()   
  4.         for (int i = 0; i < size; i++)   
  5.             ; // ...   
  6.     }   
  7. }  

class CEL_fixed {

    void method (Vector vector) {

        int size = vector.size ()

        for (int i = 0; i < size; i++)

            ; // ...

    }

}

 

 

二、为'Vectors' 'Hashtables'定义初始大小


JVM
Vector扩充大小的时候需要重新创建一个更大的数组,将原原先数组中的内容复制过来,最后,原先的数组再被回收。可见Vector容量的扩大是一个颇费时间的事。
通常,默认的10个元素大小是不够的。你最好能准确的估计你所需要的最佳大小。

例子:

Java代码

  1. import java.util.Vector;   
  2. public class DIC {   
  3.     public void addObjects (Object[] o) {   
  4.         // if length > 10, Vector needs to expand   
  5.         for (int i = 0; i< o.length;i++) {       
  6.             v.add(o);   // capacity before it can add more elements.   
  7.         }   
  8.     }   
  9.     public Vector v = new Vector();  // no initialCapacity.   
  10. }  

import java.util.Vector;

public class DIC {

    public void addObjects (Object[] o) {

        // if length > 10, Vector needs to expand

        for (int i = 0; i< o.length;i++) {   

            v.add(o);   // capacity before it can add more elements.

        }

    }

    public Vector v = new Vector();  // no initialCapacity.

}

 



更正:
自己设定初始大小。

Java代码

  1. public Vector v = new Vector(20);     
  2.    public Hashtable hash = new Hashtable(10);   

 public Vector v = new Vector(20); 

    public Hashtable hash = new Hashtable(10);

 


参考资料:
Dov Bulka, "Java Performance and Scalability Volume 1: Server-Side Programming
Techniques" Addison Wesley, ISBN: 0-201-70429-3 pp.55 – 57

三、在finally块中关闭Stream


程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。
         
例子:

Java代码

  1. import java.io.*;   
  2. public class CS {   
  3.     public static void main (String args[]) {   
  4.         CS cs = new CS ();   
  5.         cs.method ();   
  6.     }   
  7.     public void method () {   
  8.         try {   
  9.             FileInputStream fis = new FileInputStream ("CS.java");   
  10.             int count = 0;   
  11.             while (fis.read () != -1)   
  12.                 count++;   
  13.             System.out.println (count);   
  14.             fis.close ();   
  15.         } catch (FileNotFoundException e1) {   
  16.         } catch (IOException e2) {   
  17.         }   
  18.     }   
  19. }  

import java.io.*;

public class CS {

    public static void main (String args[]) {

        CS cs = new CS ();

        cs.method ();

    }

    public void method () {

        try {

            FileInputStream fis = new FileInputStream ("CS.java");

            int count = 0;

            while (fis.read () != -1)

                count++;

            System.out.println (count);

            fis.close ();

        } catch (FileNotFoundException e1) {

        } catch (IOException e2) {

        }

    }

}

 


         
更正:
在最后一个catch后添加一个finally

参考资料:
Peter Haggar: "Practical Java - Programming Language Guide".
Addison Wesley, 2000, pp.77-79

四、使用'System.arraycopy ()'代替通过来循环复制数组


'System.arraycopy ()'
要比通过循环来复制数组快的多。
         
例子:

Java代码

  1. public class IRB   
  2. {   
  3.     void method () {   
  4.         int[] array1 = new int [100];   
  5.         for (int i = 0; i < array1.length; i++) {   
  6.             array1 [i] = i;   
  7.         }   
  8.         int[] array2 = new int [100];   
  9.         for (int i = 0; i < array2.length; i++) {   
  10.             array2 [i] = array1 [i];                 // Violation   
  11.         }   
  12.     }   
  13. }  

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

        }

    }

}

 


         
更正:

Java代码

  1. public class IRB   
  2. {   
  3.     void method () {   
  4.         int[] array1 = new int [100];   
  5.         for (int i = 0; i < array1.length; i++) {   
  6.             array1 [i] = i;   
  7.         }   
  8.         int[] array2 = new int [100];   
  9.         System.arraycopy(array1, 0, array2, 0100);   
  10.     }   
  11. }  

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);

    }

}

 


         
参考资料:
http://www.cs.cmu.edu/~jch/java/speed.html

五、让访问实例内变量的getter/setter方法变成”final”


简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载,所以,可以变成”inlined”

例子:

Java代码

  1. class MAF {   
  2.     public void setSize (int size) {   
  3.          _size = size;   
  4.     }   
  5.     private int _size;   
  6. }  

class MAF {

    public void setSize (int size) {

         _size = size;

    }

    private int _size;

}

 



更正:

Java代码

  1. class DAF_fixed {   
  2.     final public void setSize (int size) {   
  3.          _size = size;   
  4.     }   
  5.     private int _size;   
  6. }  

class DAF_fixed {

    final public void setSize (int size) {

         _size = size;

    }

    private int _size;

}

 



参考资料:
Warren N. and Bishop P. (1999), "Java in Practice", p. 4-5
Addison-Wesley, ISBN 0-201-36065-9

六、避免不需要的instanceof操作


如果左边的对象的静态类型等于右边的,instanceof表达式返回永远为true
         
例子:

Java代码

  1. public class UISO {   
  2.     public UISO () {}   
  3. }   
  4. class Dog extends UISO {   
  5.     void method (Dog dog, UISO u) {   
  6.         Dog d = dog;   
  7.         if (d instanceof UISO) // always true.   
  8.             System.out.println("Dog is a UISO");   
  9.         UISO uiso = u;   
  10.         if (uiso instanceof Object) // always true.   
  11.             System.out.println("uiso is an Object");   
  12.     }   
  13. }  

public class UISO {

    public UISO () {}

}

class Dog extends UISO {

    void method (Dog dog, UISO u) {

        Dog d = dog;

        if (d instanceof UISO) // always true.

            System.out.println("Dog is a UISO");

        UISO uiso = u;

        if (uiso instanceof Object) // always true.

            System.out.println("uiso is an Object");

    }

}

 


         
更正:         
删掉不需要的instanceof操作。

Java代码

  1. class Dog extends UISO {   
  2.     void method () {   
  3.         Dog d;   
  4.         System.out.println ("Dog is an UISO");   
  5.         System.out.println ("UISO is an UISO");   
  6.     }   
  7. }  

class Dog extends UISO {

    void method () {

        Dog d;

        System.out.println ("Dog is an UISO");

        System.out.println ("UISO is an UISO");

    }

}

 

 

七、避免不需要的造型操作


所有的类都是直接或者间接继承自Object。同样,所有的子类也都隐含的等于其父类。那么,由子类造型至父类的操作就是不必要的了。
例子:

Java代码

  1. class UNC {   
  2.     String _id = "UNC";   
  3. }   
  4. class Dog extends UNC {   
  5.     void method () {   
  6.         Dog dog = new Dog ();   
  7.         UNC animal = (UNC)dog;  // not necessary.   
  8.         Object o = (Object)dog;         // not necessary.   
  9.     }   
  10. }  

class UNC {

    String _id = "UNC";

}

class Dog extends UNC {

    void method () {

        Dog dog = new Dog ();

        UNC animal = (UNC)dog;  // not necessary.

        Object o = (Object)dog;         // not necessary.

    }

}

 


         
更正:

Java代码

  1. class Dog extends UNC {   
  2.     void method () {   
  3.         Dog dog = new Dog();   
  4.         UNC animal = dog;   
  5.         Object o = dog;   
  6.     }   
  7. }  

class Dog extends UNC {

    void method () {

        Dog dog = new Dog();

        UNC animal = dog;

        Object o = dog;

    }

}

 


         
参考资料:
Nigel Warren, Philip Bishop: "Java in Practice - Design Styles and Idioms
for Effective Java".  Addison-Wesley, 1999. pp.22-23

八、如果只是查找单个字符的话,用charAt()代替startsWith()


用一个字符作为参数调用startsWith()也会工作的很好,但从性能角度上来看,调用用String API无疑是错误的!
         
例子:

Java

你可能感兴趣的:(java,jvm,performance)