优化的目的:
1、提高代码运行的效率 2、减小代码的体积
1、把一个基本数据类型转为字符串,基本数据类型.toString()是最快的方式、String.valueOf(数据)次之、数据+””最慢
(1)String.valueOf()方法底层调用了Integer.toString()方法,但是会在调用前做空判断
(2)Integer.toString()方法就不说了,直接调用了
(3)str+ “”底层使用了StringBuilder实现,先用append方法拼接,再用toString()方法获取字符串
三者对比下来,明显是2最快、1次之、3最慢
2、
字符串变量和字符串常量equals的时候将字符串常量写在前面,防止空指针出现
例如:变量str,防止为null
- String str = “abc”;
- if (str.equals(“abc”)) {
- ....
- }
3、
循环内不要不断创建对象引用,重复创建对象消耗内存
- 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罢了,但是内存中只有一份,这样就大大节省了内存空间了。
4、
基于效率和类型检查的考虑,应该尽可能使用array,无法确定数组大小时才使用ArrayList,
尽量使用HashMap、ArrayList、StringBuilder,除非线程安全需要,否则不推荐使用Hashtable、Vector、StringBuffer,后三者由于使用同步机制而导致了性能开销
5、不要创建一些不使用的对象,不要导入一些不使用的类
这毫无意义,如果代码中出现”The value of the local variable i is not used”、”The import java.util is never used”,那么请删除这些无用的内容,(有注释的代码容易产生该问题)
6、当复制大量数据时,使用System.arraycopy()命令
7、乘法和除法使用移位操作,(记得加上注释)
- 例如:
-
- for (i = 0; i < 200; i++){
- a = val *4;
- b = val / 8;
- }
-
- 用移位操作可以极大地提高性能,因为在计算机底层,对位的操作是最方便、最快的,因此建议修改为:
-
- for (i = 0; i < 200; i++){
- a = val << 2;
- b = val >> 3;
- }
8、尽量在合适的场合使用单例
使用单例可以减轻加载的负担、缩短加载的时间、提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:
(1)控制资源的使用,通过线程同步来控制资源的并发访问
(2)控制实例的产生,以达到节约资源的目的
(3)控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信
9、使用数据库连接池和线程池
这两个池都是用于重用对象的,前者可以避免频繁地打开和关闭连接,后者可以避免频繁地创建和销毁线程
10、不要让方法中有太多的形参,参数太多势必导致方法调用的出错概率增加,可以封装成一个一个实体对象,作为参数
11、对资源的close()建议分开操作
- try{
- XXX.close();
- YYY.close();
- }catch (Exception e) {
- }
-
- 建议修改为:
-
- try{
- XXX.close();
- }catch (Exception e)
- {}
- try{
- YYY.close();
- }catch (Exception e)
- {}
虽然有些麻烦,但是可以防止,xxx关闭,抛出异常,导致yyy没有关闭的结果,可以防止内存泄漏,导致内存溢出的结果。
12、输入和输出(I/O)
输入和输出包括很多方面,但涉及最多的是对硬盘,网络或数据库的读写操作。对于读写操作,又分为有缓存和没有缓存的;对于数据库的操作,又可以有多种类型的JDBC驱动器可以选择。但无论怎样,都会给程序的性能带来影响。因此,需要注意如下几点:
(1) 使用输入输出缓冲
尽可能的多使用缓存。但如果要经常对缓存进行刷新(flush),则建议不要使用缓存。
(2) 输出流(Output Stream)和Unicode字符串
当时用Output Stream和Unicode字符串时,Write类的开销比较大。因为它要实现Unicode到字节(byte)的转换.因此,如果可能的话,在使用Write类之前就实现转换或用OutputStream类代替Writer类来使用。
(3)当需序列化时使用transient
当序列化一个类或对象时,对于那些原子类型(atomic)或可以重建的原素要表识为transient类型。这样就不用每一次都进行序列化。如果这些序列化的对象要在网络上传输,这一小小的改变对性能会有很大的提高。
(4) 使用高速缓存(Cache)
对于那些经常要使用而又不大变化的对象或数据,可以把它存储在高速缓存中。这样就可以提高访问的速度。这一点对于从数据库中返回的结果集尤其重要。
13、尽量使用局部变量。
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量,实例变量等,都在堆(Heap)中创建,速度较慢。
14、在java+Oracle的应用系统开发中,java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担
15、代码重构,增加代码的可读性
16、int整数相乘溢出
我们计算一天中的微秒数:
- long microsPerDay = 24 * 60 * 60 * 1000 * 1000;
- System.out.println(microsPerDay);
问题在于计算过程中溢出了。这个计算式完全是以int运算来执行的,并且只有在运算完成之后,其结果才被提升为long,而此时已经太迟:计算已经溢出。
解决方法使计算表达式的第一个因子明确为long型,这样可以强制表达式中所有的后续计算都用long运算来完成,这样结果就不会溢出:
- long microsPerDay = 24L * 60 * 60 * 1000 * 1000;
17、尽量减少对变量的重复计算。
比如 :
应修改为 :
- for(int i=0,len=list.size();i
18、使用同步代码块替代同步方法
这点在多线程模块中的synchronized锁方法块一文中已经讲得很清楚了,除非能确定一整个方法都是需要进行同步的,否则尽量使用同步代码块,避免对那些不需要进行同步的代码也进行了同步,影响了代码执行效率。
19、尽量避免循环中执行查询操作(减少不必要的数据库查询操作 )
20、三元表达式代替if else
简化逻辑判断,是代码更加清晰、一目了然。
public String express(boolean flag) {
return flag ? "成功" : "失败";
}
21、Session管理
(1)避免JSP页面的Session频繁创建
(2)及时清理不需要的Session
22、使用单元测试代替main方法
对程序中关键细节的功能添加单元测试,这些单元测试可以保留在系统中,提供给测试人员使用、
方便统计单元测试覆盖率等等;降低程序在测试人员测试前出错的频率;如使用Junit等测试工具来实现。