目录
一. 常量与变量
1. 直接使用常量本身赋值,而不是直接创建一个新对象。后者一定会在堆内创建一个新对象,前者可能使用到常量池。
2. 当类成员变量无需改变时,使用常量static限制住。 因为对象中的普通成员变量会每个对象一份,而静态变量只有一份,避免浪费堆内内存。
3. 不要基本数据类型和包装类型交替使用。尤其是循环内,尽量使用包装类型为好,可以自己判空,避免null包装类型赋值给基本数据类型,直接产生NPE。
4. 如果变量的初始值一定会被覆盖,就没必要给变量付初始值。因为初始值会申请堆内存,也会增加垃圾回收器工作量。
5. 尽量使用函数内的基本类型的临时变量。
函数内,基本类型的临时变量和参数保存在栈中,访问较快。
函数内,对象类型临时变量和参数,其引用保存在栈中,内容保存在堆中,访问较慢。
类内,所有类型的成员变量都保存在堆中,访问较慢。
如果可以的话,尽量在函数内使用基本类型的临时变量和参数,保证访问相对较快。
6. 尽量不要在循环体外定义变量
新版jdk优化后,循环体内体外定义的变量效率都是一样的,这里是原本循环体内频繁创建会增加垃圾回收压力和浪费堆空间。但编译器堆这一部分做了优化,字节码创建的变量实际是在循环体外的。不过在循环体外定义变量,不符合"局部变量作用域最小化"的原则,可能延长对象的生命周期延缓垃圾回收。
7. 不可变的静态变量,虽然需要支持多线程访问,也可以使用非线程安全类。可以加快访问速度。
8. 不可变的成员变量,虽然需要支持多线程访问, 也可以使用非线程安全类。 可以加快访问速度。
二. 类与对象
1. 不推荐使用json来完成对象converter。利用json对象转换为字符串,在将字符串装换为对象,功能上可以实现,但是性能存在问题。
2. 尽量不使用反射完成对象converter。例如BeanUtils.copyProperties(Object source, Object target);性能上有下降。
3 尽量使用lamada表达式代替匿名函数类。 lamada表达式在大多数jvm内使用invokeDynamic实现,效率比匿名内部类高。
4. 尽量不要定义不必要的匿名内部类,对一个类就多一次类加载过程。
三. 方法
1. 把和类成员变量无关的方法变为static方法。我理解,如果该方法不依赖当前类的成员变量,就不应该在类里, 可以提取到工具类里面,成员工具类静态方法。
2. 尽量使用方法传递代替值传递;尽量使用方法传递代替值传递,可以避免不必要的方法计算,比如Optional的orElse(T value)方法和orElseGet(Supplier supplier)方法,其中orElse(T value)方法无论前面Optional容器之是null还是nonNull,都会提前执行orElse里面的方法。而orElseGet(()-》return xxx)方法并不会,只会在Optional容器值为null时才调用orElaseGet里面的方法。
四. 表达式与字符串
1. 尽量减少使用重复的方法调用,比如循环判断条件。
2. 尽量减少不必要的方法调用,比如某些变量会被覆盖,提前赋值(初始化) 会导致cpu浪费。
3. 提取公共表达式,避免重复计算。
4, 字符串在拼接的时候,尽量使用StringBuilder,避免创建太多的临时变量字符串,尤其是循环体内。
五. 数组和集合
1. 不要使用循环拷贝数组,尽量使用System.arraycopy拷贝数组。
推荐使用System.arraycopy拷贝数组,也可以使用Arrays.copyOf拷贝数组。
2. 集合转换为类型T数组时,尽量传入空数组T[0]。
3. 不要使用循环拷贝集合,而是用jdk自带的方法,比如addAll(),因为使用循环可能产生扩容,使用addAll会提前知道预计容量。
4. 将数据转换为列表,尽量使用Array.asList()。避免使用循环进行拷贝,原因同上。
5. 判空使用isEmpty() 而不是size() == 0 ,前者时间复杂度o(1),后者的时间复杂度可能是o(n)
6. 不管列表支不支持随机访问,都是用迭代进行遍历。
列表分为支持随机访问和不支持随机访问,比如linkedList即不支持随机访问。
不支持随机访问的列表,使用get(index)进行遍历效率极低。
7. 避免先判断contain在进行获取get, 可以直接获取get,进行判空,后者避免了前者的两次查找。
六. 异常
1. 不要在循环体内捕获异常,过多的异常代码会降低效率,在外面一样可以捕获循环中出现的异常。
2. 如果可以使用条件表达式,禁止使用异常控制业务流程,后者效率低。
七. 缓冲区
1. 初始化缓冲区,尽量指定大小,避免穿线频繁缓冲区扩容。
2. 尽量重复利用缓冲区,缓冲区较大,多次创建耗费时间长,也增加了垃圾回收
使用setLength方法让缓冲区重新从0开始,以便重复利用。
从设计上,就开始尽量使用一个缓冲区。
3. 尽量使用缓冲流减少IO操作。
八. 线程
1. 在单线程中,尽量使用非线程安全类,避免多线程访问控制的开销。
2. 在多线程中,尽量使用线程安全类,避免自己写线程安全控制代码,前者更简洁,更高效。
3. 尽量减少同步代码块的范围。
4. 同步代码块,能合并尽量合并,避免代码块多次进入和释放带来的开销。
5. 尽量使用线程池,减少单独创建新线程,避免线程频繁创建的开销。