Java代码优化
用到的时候再定义(懒加载)
如上图中,获取(定义)isEnable的值的代码应该紧跟着放在判断(使用)isEnable的代码块的上面。
一者如果smsRecordList为空,则程序直接返回,isEnable不会被使用,白白的浪费了部分栈空间(内存);
二者避免提前占用栈空间,内存占用过高会影响性能。
延迟操作数据库
如上图中,第二块标记的代码应该放在第一块标记的代码前面。
第一块代码通过查询数据库来做逻辑验证,比较耗时;
第二块标记的代码则只是验证参数中的验证码是否为空,没有操作数据库,速度会很快,而且验证不通过程序将直接返回(第二块代码是第一块代码的必要条件)。
将第二块代码放在第一块代码的前面,可以避免无用的查询,尽快返回,提升程序效率。
不要重复造轮子
使用已封装好的代码、组件。
如上面的判断字符串是否为空的代码,如果自己写的话需要注意NullPointException,我们可以使用apache已经封装好的、被广泛使用的方法StringUtils.isBlank,避免出现低级错误。
同样的对于一些复杂组件,自己实现的话比较复杂而且需要处理各种异常,费时费力,而且可能无法得到一个很好的结果。
除非必要,不要使用线程安全类
Jdk中提供的普通的线程安全类如HashTable,Vector,StringBuffer都是使用synchronize关键字实现,效率低(抢占锁),并且会造成线程阻塞。
在不要求线程安全的场景中可以使用HashMap,ArrayList/LinkedList,StringBuilder等替代,在要求线程安全的场景中则可以根据情况使用ConcurrentHashMap,CopyOnWriteList等替代。
复用代码(减少代码量)
一个方法的长度不要超过80行,超过80行则要注意抽取封装部分操作,并注意复用。
如上图中,验证验证码、身份证号码、年龄都可以抽取封装成新的方法,这些方法是通用方法,别处也可以复用(不用重复造轮子)。
避免创建过多的变量
最常见的如字符串拼接,由于字符串是不变类,每次更新都会创建新的字符串变量(有些会是增加多个字符串常量),一者占用过多的内存不能及时回收(方法未结束),二者每次创建新的字符串都需要有变量接收(赋值),效率低。
做拼接操作时应使用StringBuilder/StringBuffer替代。
初始化长度
集合类如Array,ArrayList ,HashMap都是基于数组的(HashMap是基于数组和链表),直接new会创建默认长度的数组(内存空间),在集合中的元素数量将要超过当前数组长度时会进行扩容。
比如直接new一个ArrayList对象,会默认创建length是16的数组。
一方面如果集合里面只需要存放少数几个元素,则会造成内存浪费;
另一方面集合扩容时,如ArrayList会直接扩展到当前数组长度的2倍,如果不能充分使用扩容后的空间,将造成更大的浪费(如当前数组长度是4096,扩容后就是8192,而只需要存放4097个元素,则有4095个空间都是浪费的);同时扩容时是创建新的数组,并将原数组中的数据迁移过来,效率较低。
可以预知集合长度的情况下,可以在创建对象时指定集合长度,如new ArrayList(16),避免资源浪费。
避免重复计算
for (int i = 0; i < list.size(); i++)
上述代码中的list.size每次循环都需要重新获取(计算)一次,可以替换为如下代码:
for (int i = 0, int length = list.size(); i < length; i++)
使用设计模式
设计模式是前人工作的总结和提炼,方便同样懂设计模式的人的理解,同时让程序拥有更合理的结构(复用性、扩展性)。