本文的主要类容来自 微信公众号 : java后端技术, (以后了解到的其余细节也会在此文中进行补充)java
1、 代码优化的目的:数据库
1,减少代码体积 : 还有助于增长代码的可阅读性(这个很重要)编程
2,提升运算效率后端
2、 代码优化细节api
一、尽可能指定类、 变量、 方法的 final 修饰符数组
带有修饰符的类是不可派生的, 在java的api中 像String之类的就是属于这类。安全
被final修饰的类不能被继承, 被final修饰的方法不能被重写。 若是指定一个类是final的,那么这个类中全部的方法都是final的。微信
文中的做者指出: java的编译器会内联全部的final方法, 这对java运行效率提高很大, (能够达到 50% 左右)。session
二、尽可能重用对象, 特别是String对象的使用, 出现字符串链接的时候, 应该使用StringBuilder 或者 StringBuffer代替, 由于java数据结构
虚拟机 不只要建立String对象(String对象为final对象,不能被改变), 这样能够减小内存中的对象信息,。
3,、若是能够的话, 尽可能使用局部变量, 局部变量 存在与 stack中, 随着方法运行的结束 而消失。 而其余的变量 则会存在与heap中, 这在
方法运行结束后 还须要额外的垃圾回收。
四、及时的关闭流, 在进行数据库链接或者 io编程的时候, 在使用完毕应立即使的关闭 用来释放资源。 由于流的操做会形成极大的性能开销。
五、尽量的减小重复的计算 , 在方法的调用的时候, 即使只有一句话,也是系统的性能开销。 在进行 集合 或者数组的遍历的时候, 其长度
能够先计算出来。尤为是在 length恒大的时候, 对性能的提升就愈加的明显
六、尽可能使用 懒加载策略, 在已经立刻须要该类的时候再去创造该类。
七、谨慎使用 异常, 在使用异常的时候 java虚拟机 就必定回去调用堆栈信息, 消耗不少资源。 因此不要为了达到某个普通的逻辑功能来使用异常。
八、try catch 语句 最好放在最外面, 不要被选择 ,循环等判断。
九、若是能估计到 最后添加的类容的长度, 能够为 底层使用数组方法、实现的集合指定长度 : ArryList 、 LinkeList 、 StringBuffer 、 StringBuidler
HashMap 、 HashSet 等。 由于 当集合数据满时, 会自动在底层建立一个 两倍当前长度的 集合,并将数据拷贝到新集合中。 而集合的初始
默认长度较小, 因此数据量较大的时候, 会建立不少 类, 消耗大量的资源。
十、当复制大量数据的时候, 使用 System.arrycopy()
十一、 乘法 和 除法使用移位操做, 这回加快计算机的执行速度
十二、循环内不要建立新的对象引用, 由于 若是循环量较大的话, 会在 stack中建立大量的临时引用。
1三、如无必要, 应当尽可能使用 array , 而不是使用 arrayList(当没法肯定数组大小的时候再使用 list)
1四、若是没有同步要求, 尽可能使用 HashMap, ArrayList, StringBuilder。 不要使用 Hashtable, Vechtor,StringBuffer
1五、不要将一个数组 声明成一个 public static final 数组声明为 final 也仍是能被改变, 而一个public 的数组明显并不安全。
1六、 在合适的场合使用单例模式 : 单例模式 能够减轻加载的负担, 减小加载的时间, 提升加载的效率,
使用场合 : 1)控制资源使用, 经过线程同步来控制资源的并发访问
2)控制数据的共享, 以达到节约资源的目的
3)控制数据共享, 再不创建直接关联的状况下, 让多个不相干的进程和线程中实现共享。
1七、尽可能避免随意使用静态变量, 一个静态的变量 通常不会被 gc 回收,。
1八、及时清除不须要的会话 session 等 。
1九、 实现 RandomAccess 接口的集合 (ArryList 等) , 应当使用普通的 for 循环 而不是 forEach循环。
由于foreach 循环底层使用的是 iterator , 其是顺序访问的, 而RandomAccess接口代表支持随记访问。
而随记访问使用 for 循环更加的高效 , 反之亦然。
20、使用同步代码块 来代替 同步方法,
2一、将常量声明为 static final ,并大写命名 : 虚拟机会将该常量放入常量池。
2二、不要建立一些不使用的 对象, 不要引入一些不使用的类。
2三、 少使用 反射, 虽然反射机制很是强大, 可是效率不过高。 建议: 在项目启动的时候 经过反射机制将要反射的地方建立出反射的对象。
2四、使用数据库链接池 和 线程池 (不用解释)
2五、使用带缓冲的输入输出流
2六、顺序插入和随机访问较多的地方 使用 ArrayList , 删除和中间插入比较多的使用 LinkedList (底层数据结构)。
2七、public 方法中不要有太多形参
2八、字符串变量 和 字符串常量进行比较的时候将 常量放在前面。
2九、在java中 i==1 和 1==i是没有什么区别的, 可是在习惯上使用 i == 1.
30、不建议对 数组使用 toString 方法, 由于 会打印成一个 哈希地址, 可是能够对 集合使用toString方法, 由于其父类中重写了 toSting方法。
3一、不要对超出范围的基本数据类型使用强制向下转型。如: 将一个 long 类型的强制转换成一个 int类型的, 这是由于 : 在java中向下转型是
切断了long 的高 32 为二进制码, 因此并不能直接获得 是、十进制上的后面位数。
3二、在公共的集合中, 不使用的类要即便清理掉, 集合没有在方法中的话, 只要对象一直存在集合就会一直存在, 随着使用的增长, 集合中的数据也会增长
当增长到必定程度时 , 有可能形成内存泄露隐患。
3三、若是将一个 基本数据类型转换成一个字符串, 那么 运行速度最快的是 toString()方法, 以后是 String.valueOf(), 在以后是 “” + “” 最慢
由于String.valueOf()底层使用的是toString方法, 而 “”+底层使用的是 Stringuilder实现的。
3四、使用最有效率的方法来遍历 Map
public static void main(String [] args){ HashMap<String, String> hm = new HashMap<String, String>; hm.put("hehe","java"); Set<Map.entry<String,String>> entrySet = hm.entrySet(); Iterator it = entrySet.iterator(); while(it.hasNext()){ ...... } }
若是只想遍历 key的话, 使用 keySet就行了
3五、对资源的 close 应当分开进行: 由于一个 close 操做的时要 使用try catch 语句进行异常处理, 若是有多个close, 当一个出现了异常
那么他后面的 close就能操做了。
3六、在使用 ThreadLocal 的时候, 在使用前 和使用后都要进行 remove 操做。
由于在使用 线程池的时候, 当一个线程使用结束以后, 会将其放入线程池中,而不会将其 销毁, 咱们拿到一个线程以后, 极可能
拿到其上绑定的其它数据, 由此形成的异常很是难以查明。
3七、应当使用 常量的定义来代替魔鬼数字(没有具体含义的数字 和 字符串), 会极大地提升可阅读性。
3八、在long 或者 Long 类型赋值的时候 应当使用 L 而不是 l, 由于 l 易于 1 混淆。
3九、全部重写的方法都应当 保留 @Override 注解
一是这样能够 知道这个放法是个重写方法,
二是可以判断你的重写是否有语法错误
三是在抽像类 或者 接口中进行 签名修改的时候, 继承类中会出现异常, 容易定义到具体的类。
40、在循环 中 不要使用 + 进行字符串的拼接, 直接使用 StringBuilder 的 apperd方法进行拼接。
前面提到过 + 操做底层使用的是 SringBuilder 进行的, 这样就会生成 循环次数 个 StringBuilder
4一、推荐使用 jdk7 中提供的 行的 Objects 类进行equals比较, 直接使用 equals 有空指针危险。
4二、不要使用多线程对 一个 Random对象进行操做, 虽然没有线程安全问题, 可是会下降性能,推荐使用 ThreadLocalRandom
4三、 静态类 、单例类 、 工厂类 的构造器使用 private