由于前一段时间,从事了一些基础控件的开发工作,很多地方都涉及到代码效率的问题。现在我把它们整理了一下,其中有一些内容是来自网友的,希望对大家有所帮助。另外,由于在之前的一篇文章中已谈到关于Java字符串的优化策略,所以这里就不再讨论了:
Java基础类型的封装类的灵活运用:
Java中提供了很多对于基础类型如int、double、boolean等类型的封装类,分别对应Integer、Double、Boolean等对象,当我们需要将一个基础类型数据转换为对应的对象时,尽量不要使用new的方式来创建,而使用每个类中提供的valueOf()方法来创建,特别的,对于Boolean,JDK提供了两个静态布尔值Boolean.TRUE和Boolean.FALSE。原因是,JDK会缓存一部分对象,以Integer为例,例如在Integer中会缓存从-128到256对应的Integer对象,当我们使用valueOf()时,虚拟机会先到缓存中获取,如果没有找到,才会创建,避免了每次都创建的可能性。
设计和创建对象的原则:
1、设计对象时,如果可能,最好将该对象设计为final的,此时,JVM可能会内联所有的方法,显著的提高程序的性能。
2、避免在程序中重复创建对象,毕竟每次创建对象都会为虚拟机带来负担。因此,如果在一个类中的某个变量会被多次引用,我们可以定义这个变量为static final 类型的,如果希望被外部使用则申明为public,否则申明为rivate类型的。而在一个方法体内部,如果一个变量会被多次使用,特别在多个for循环的环境下,我们可以申明为final类型。
3、另外,当有复杂的数据对象,且他们之间存在相互的关联信息(例如,这些数据是来自websphere多张关联表),前台程序需要频繁访问这些数据信息时,我们还可以将这些数据封装成的对象信息放入缓存中组织起来,不仅避免了频繁的网络传输,同时也避免了频繁的对象创建,可以为程序带来很大的效率。
异常处理的使用原则:
1、当进行数据库操作时,需要注意异常处理的使用方式,不能为所有的语句只使用一个try...catch(虽然这样很省事),这样很容易导致某些 资源释放失败,如下方式:
try {
Connection conn = ...
try {
ResultSet rs = conn.prepareStatement("");
...
} finally {
rs.close();
}
} finally {
conn.close();
}
2、另外,使用try...catch时,会极大程度上降低虚拟机的性能,因此需要谨慎使用,特别是在一些高频率的访问代码处或一些循环中,需要慎重考虑,如果没有必要,尽量不要使用,否则你的程序性能会大打折扣。因为抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因此消耗一些性能。
3、需要记住的一点是,异常应当仅用于有错误发生时,而不要用于控制流。
集合框架的选择原则:
集合框架的结构如下:
Collection是集合接口
|————Set子接口:无序,不允许重复。检索元素效率低下,删除和插入效率高
|————HashSet:以哈希表的形式存放元素,插入删除速度很快
|————List子接口:有序,可以有重复元素。查找元素效率高,插入删除元素效率低
|————ArrayList:动态数组,因此每次创建时,如果能够确定数组的个数,请指定个数,这样会提高很多效率
|————LinkedList:包括链表、队列、堆栈,当进行大量插入操作时,该对象比ArrayList好,但查找速度不及ArrayList
数组相关的操作原则:
1、如果我们希望获取一个较长的字符串中某个位置的字符信息,不要操作charAt()方法获取,可以先调用toCharArray()将其转换为字符数组,然后通过索引来获取。
2、如果我们需要对数组进行拷贝操作时,尽量调用System.arraycopy()方法来实现,而不要使用循环来复制。
其他原则:
1、一些地方,我们可以通过位运算来替代乘除法,提高代码效率。
2、尽量减少对变量的重复计算,例如for(int i = 0;i < list.size; i ++)可以修改为int size=list.size, for(int i=0; i<size; i++)。
3、如果没有多线程访问的问题,尽量使用HashMap 和ArrayList,不推荐使用HashTable和Vector ,后者由于使用同步机制,而导致了性能的开销。
4、日期类型的对象会占用很大的空间,如果你要存储大量的日期对象,可以考虑把它存储为long型,然后在使用的时候转换为Date类型。