Java编码技巧与代码优化
本文参考整理自https://mp.weixin.qq.com/s/-u6ytFRp-ZAqdLBsMmuDMw
对于在本文中有所疑问的点可以去该文章查看详情
常量&变量
-
直接赋值常量值, 禁止声明新对象,如
Long i = new Long(1L);
-
当成员变量值无需改变时, 尽量定义为静态常量
-
尽量使用基本数据类型, 避免自动装箱和拆箱
-
如果变量会被覆盖就没必要赋初值
-
尽量使用函数内的基本类型临时变量
-
函数内, 基本类型的参数和临时变量都保存在栈中, 访问速度较快. 对象类型的参数和临时变量和引用都保存在栈中, 而内容都保存在堆中, 访问速度较慢
-
在类中, 任何类型的成员变量都保存在堆中
-
-
尽量不要在循环体外定义变量, 避免延长大对象生命周期导致延缓回收问题
-
不可变的静态常量和成员变量, 尽量使用非线程安全类
对象&类
-
禁止使用JSON转化对象, 应该手动包装来转化对象
-
先转化为JSON字符串再转为对应对象可以实现转化对象, 但是性能上存在问题
-
-
尽量不使用通过反射赋值对象, 会造成性能下降, 比如DTO取值赋值到VO
-
匿名内部类采用Lambda表达式, 因为Lambda表达式在大多数虚拟机中采用invokeDynamic指令实现, 效率会比匿名内部类更高
-
尽量避免定义不必要的子类,多一个类就需要多一份类加载
-
尽量指定类和方法的final修饰符
-
Java编译器会寻找机会内联所有的final, 具体参见Java运行期优化, 能够使性能平均提高50%
-
方法
-
把和类成员变量无关的方法声明为静态方法
-
尽量使用基本数据类型作为参数类型和返回值类型, 避免不必要的装箱拆箱和空指针判断
-
协议编程, 协议方法参数值与返回值非空
-
避免多余的判空处理
-
避免不必要的函数封装, 方法调用引起的额入栈和出栈会导致更多的CPU和内存消耗, 不过为了代码的简洁和清晰, 增加一定的方法是值得的
-
减少方法的重复调用
-
for (int i = 0, userLength = userList.size(); i < userLength; i++) {
...
}
-
-
尽量避免不必要的方法调用, 其实就是避免出现 调用了一个方法并将结果赋值, 赋的值还未起到作用, 就被覆盖了 的情况发生
-
尽量使用移位来代替正整数乘除
-
提取公共表达式
-
尽量少在条件表达式中用 ! 取反
-
当高于5个分支时, switch语句效率更高, 而非if else
字符串
-
尽量不要使用正则表达式匹配
-
尽量使用字符替换字符串, 因为字符长度固定为1, 查找和匹配的效率自然高
-
使用StringBuilder进行字符串拼接
-
使用String.valueOf来进行字符串转化
数组
-
使用System.arraycopy进行拷贝数组
-
集合转化为类型T数组时, 尽量传入空数组T[0]
-
集合转化为Object数组时, 尽量使用toArray()方法而非toArray(new Object[0])
集合
-
初始化集合时, 尽量指定大小, 减少扩容次数
-
尽量使用addAll()来批量拷贝
-
使用Arrays.adList()转化数组为列表
-
直接迭代需要使用的集合
-
不要用size()方法检测空, 用isEmpty方法检测, 因为某些size方法实现的时间复杂度可能是O(n)
-
尽量使用迭代遍历来代替for循环里get()
-
尽量使用HashSet判断值存在
-
避免先判断存在再获取, 因为会造成二次查找, 直接获取然后判断是否为空
异常
-
直接捕获各种异常, 而非instanceof
-
避免在循环中捕获, 在循环体外捕获可以提高执行效率
-
禁止使用异常控制业务流程, 比如 抛了异常就返回false
缓冲区
-
尽量重复使用同一缓冲区
-
使用缓冲流减少IO操作
线程
-
单线程中, 尽量使用非线程安全类
-
多线程中, 尽量使用线程安全类
-
尽量减少同步代码块范围
-
尽量合并为同一同步代码块
-
尽量使用线程池来减少线程开销