本文由网上资料初步整理,仅供于学习交流,下班后再上传完整的优化笔记,如有侵权请尽快联系小编,如有不足,可发表评论,谢谢 资料下载
Howard 于 2018/6/22 10:24 修改
序号 | 优化点 | 细节 |
---|---|---|
1、 | try{}catch(){}使用 | • 循环中不要使用try{}catch(){}语句 • 查询中不要使用try{}catch(){}语句 • try{}catch(){}异常处理,捕获对应异常类型 不要对于所有的异常捕获都使用Exception,最好是捕获对应的异常类型。异常捕获了就需要做相应的处理,而大多数人并未处理,更多的是打印一句e.printStackTrace(); 就了事了,这样做是不好的。 • try{}catch(){}的finally中销毁对象或释放资源 • 对外提供的接口有异常则抛出 |
2、 | 减少使用new关键字创建对象 | • 避免在循环中使用new关键字创建对象 • 有必要创建对象时才进行创建 |
3、 | 乘除法是否可以使用移位运算 | • 乘数或除数是否是2的平方根 • 乘除运算在循环中反复出现 |
4、 | 注意循环的写法 | • 减少循环次数变量的读取 for(int i=0,j=list.size();i < j; i++) • 循环中嵌套循环将小循环写在外层 • 不要在循环中频繁声明对象 Map<String, Object> map; for (int i = 0, j = 1000000; i < j; i++) {map = new HashMap<String, Object>();// 不再每次都做声明了} • 循环中不要调用同步方法 synchronized • 尽量避免循环中执行查询操作 |
5、 | 实现字符串拼接 | • String • 不可变字符数据类的拼接,每次使用“+=”时都相当于引入了一个中间的临时变量,所以这种方式最值得诟病。 • StringBuilder • 可变字符串对象,可以确保当前线程只有一个StringBuffer对象在实现字符串长度的修改变化,但此对象却不是线程安全的。 • StringBuffer • 可变字符串对象,此对象是线程安全的,可以确保当前线程只有一个StringBuffer对象在实现字符串长度的修改变化。 • 单个字符相加用’’代替”” string = “abc” + ‘d’; |
6、 | 提升HashMap遍历效率 | 优: for (Entry<String, String[]> entry : paraMap.entrySet()) { values = entry.getValue(); //System.out.println(values[0]);} 劣: for(String appFieldDefId : appFieldDefIds) { values = paraMap.get(appFieldDefId); // System.out.println(values[0]);} |
7、 | 尽量使用局部变量 | • 临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。 |
8、 | 尽量实现对象重用 | • 字符串对象重用 StringBuffer • 声明对象的重用 • 减少对象初始化 • 合理使用继承和抽象 |
9、 | 将闲置的资源进行释放 | • 记得断开数据库访问链接 • 记得关闭I/O输入输出流 • 对象使用完成后进行置空 list = null; |
10、 | ArrayList、Vector、LinkedList的使用 | • ArrayList实现随机查找和遍历 • Vector实现数组同步操作 • LinkedList数据的动态插入和删除 |
11、 | synchronized的使用 | • 方法的同步 • 代码块同步 |
12、 | 三元表达式代替if else | |
13、 | StringTokenizer代替substring()和indexOf() | • StringTokenizer 可以理解为String的字符标记对象,此对象可以实现字符串的截取操作,避免了字符串容易导致StringIndexOutOfBoundsException的问题。 |
14、 | System.arraycopy()实现数组值的拷贝 | |
15、 | instanceof判断接口而不是接口的实现类 | • 如果需要判断一个类是接口还是实现类,不要对这个类进行实现类判断,使用instanceof进行判断该类是否为接口,效率更高 |
16、 | 将类中不变的实例静态化 | |
17、 | 减少不必要的数据库查询操作 | • 如果在一次查询中有两个或两个以上的相同查询操作,可以考虑将第一次查询的结果缓存起来,在此次查询中以后的查询读取缓存对象就行了。 |
18、 | 尽量指定类的final修饰符 | |
19、 | 仅查找单个字符用charAt()代替startsWith() | |
20、 | transient修饰字段规避序列化持久化操作 | |
21、 | 清理程序中多余的代码 | • 删除不必要的测试代码 • 删除无效代码行 • 删除不规范的注释 |
22、 | Session管理 | • 避免JSP页面的Session频繁创建 • 及时清理不需要的Session |
23、 | 使用单元测试代替main方法 | • 对程序中关键细节的功能添加单元测试,这些单元测试可以保留在系统中,提供给测试人员使用、方便统计单元测试覆盖率等等;降低程序在测试人员测试前出错的频率;如使用Junit等测试工具来实现。 |
24、 | 对资源的close()建议分开操作 | 劣:try{ XXX.close(); YYY.close();} catch (Exception e){...} 优: try{ XXX.close(); }catch (Exception e) { ... } try{ YYY.close(); }catch (Exception e) { ... } |
25、 | 转字符串 | • 把一个基本数据类型转为字符串,基本数据类型.toString()是最快的方式、String.valueOf(数据)次之、数据+””最慢 |
26、 | 公用的集合类中不使用的数据一定要及时remove掉 | |
27、 | 不要对超出范围的基本数据类型做向下强制转型 | |
28、 | 不要对数组使用toString()方法 | |
29、 | 请知道,在java中if (i == 1)和if (1 == i)是没有区别的,但从阅读习惯上讲,建议使用前者 | |
30、 | 字符串变量和字符串常量equals的时候将字符串常量写在前面 | • if (“123”.equals(str)) 这么做主要是可以避免空指针异常 |
31、 | 不要让public方法中有太多的形参 | |
32、 | 顺序插入和随机访问比较多的场景使用ArrayList,元素删除和中间插入比较多的场景使用LinkedList | |
33、 | 使用带缓冲的输入输出流进行IO操作 | • 带缓冲的输入输出流,即BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream,这可以极大地提升IO效率 |
34、 | 使用数据库连接池和线程池 | • 这两个池都是用于重用对象的,前者可以避免频繁地打开和关闭连接,后者可以避免频繁地创建和销毁线程 |
35、 | 程序运行过程中避免使用反射 | • 特别是Method的invoke方法 |
36、 | 不要创建一些不使用的对象,不要导入一些不使用的类 | |
37、 | 使用同步代码块替代同步方法 | |
38、 | 实现RandomAccess接口的集合比如ArrayList,应当使用最普通的for循环而不是foreach循环来遍历 | |
39、 | 尽量避免随意使用静态变量 | |
40、 | 尽量在合适的场合使用单例 | |
41、 | 不要将数组声明为public static final | |
42、 | 尽量使用HashMap、ArrayList、StringBuilder,除非线程安全需要,否则不推荐使用Hashtable、Vector、StringBuffer,后三者由于使用同步机制而导致了性能开销 | |
43、 | 基于效率和类型检查的考虑,应该尽可能使用array,无法确定数组大小时才使用ArrayList | |
44、 | 尽量采用懒加载的策略,即在需要的时候才创建 | 劣:String str = "aaa"; if (i == 1){ list.add(str); } 优: if (i == 1) {String str = "aaa"; list.add(str);} |