30个精简代码的小技巧
除非线程安全需要,否则不推荐使用Hashtable,Vector
,StringBuffer,后三者由于使用同步机制而导致了性能开销。
15.不要将数组声明为public static final
因为这样毫无意义,这样知识定义了引用为static,final,数组的内容还是可以随意改变的,将
数组声明为一个public更是一个安全漏洞,这意味着整个数组可以被外部类所改变。
16.尽量在何时的场合使用单例
使用单例可以减轻加载的负担,缩短加载时的时间,提高加载的效率,但并不是所有的地方都
适用于单例,简单说,单例主要适用于以下三个方面:
(1) 控制资源的使用,通过线程同步来控制资源的并发访问;
(2) 控制实例的产生,达到节约资源的目的;
(3) 控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信。
17.尽量避免随意使用静态变量
因为当某个对象被定义为static时,gc通常是不会回收这个对象所占有的堆内存的,
如:
public class A {
private static B b = new B();
}
此时静态变量b的生命周期与A类相同,如果A类不被卸载,那么引用B指向的B对象会一直
存在内存中,直到程序终止。
18.及时清除不再需要的会话
当应用服务器需要保存更多会话时,如果内存不足,操作系统会把部分数据转移到磁盘里,
应用服务器也可能根据MRU(最近频繁使用的会话)算法,把部分不活跃的会话转存到磁盘里,
甚至可能抛出内存不足的异常。如果会话要被转存到磁盘,就必须先序列化,在大规模集群
中,对对象进行序列化代价是很大的。因此,应及时调用HttpSession的invalidate()方法
清除会话。
19.实现RandomAccess接口的集合比如ArrayList,应当使用for循环而不是foreach来遍历
JDK API对于RandomAccess接口的解释是:实现RandomAccess接口用来表明其支持快速随机
访问,此接口的主要目的是允许一般的算法更改其行为,从而将其应用到随机或连续访问列表
时能够提供良好的性能。
实现RandomAccess接口类实例,加入是随机访问的,使用for循环比foreach效率高;如果不是
随机访问的使用foreach效率高。
如:
if(list instanceof RandomAccess) {
for(int i = 0 ;i < ();i++){}
} else {
for(List li : list) {
(li);
}
}
foreach底层实现原理就是迭代器(iterator)
20.使用同步代码块代替同步方法
除非能确定整个方法都是需要进行同步的,否则尽量使用同步代码块,避免对那些不需要
同步的代码也进行同步,从而影响效率。
21.将常量声明为 STATIC FINAL
这样在编译运行时就可以把这些内容放入常量池中,避免运行期间计算生成常量的值。另外,
将常量的名字进行大写的原因。
22.程序运行过程中避免使用反射
反射是java提供给用户一个很强大的功能,但是功能强大效率却不是很高。不建议在程序运行
过程中频繁是哦那个反射机制,特别是Method的invoke方法。如果确实必要,建议将那些需要通过
反射加载的类在项目启动的时候通过反射实例化出一个对象并放入内存。
23.使用数据库连接池和线程池
这两个池都是重用与对象的,前者可以避免频繁打开和关闭连接:
后者可以避免频繁创建和销毁线程。
24.使用带缓冲的输入,输出流进行I/O操作
带缓冲的输入,输出流即:
BufferedReader,bufferedWrite,BufferedInputStream,BufferedOutputStream
它们可以大大提升I/O的效率
25.顺序插入和随机访问比较多的场景使用ArrayList,元素删除和中间插入比较多的
场景使用LinkedList
理解这两个集合有何不同即可
26.不要让public方法中有太多形参
public方法是对外提供的方法,如果给这些方法太多形参的话有两点坏处:
(1) 违反面相对象的思想,java讲究万物皆对象,太多形参,和java编程
思想不和
(2) 参数较多会导致出错概率增加
27.字符串变量和字符串常量equals的时候将字符串常量写在前面
如:
Strring str = "123";
if(("123")) {
}
可以替换为:
Strring str = "123";
if("123".equals(str)) {
}
这么做是为了避免空指针的出现(中期项目有讲过)
28.不要对数组使用toString()方法
本意是想打印数组里的内容,却可能因为数组引用对象为空而导致空指针异常。虽然对数组
toString()没有意义,但是对集合toString()是可以打印出集合中的内容的,因为集合的父类
AbstractCollections重写了Object的toString()方法。
29.不要对超出范围的基本数据类型做向下强制转换
得到的结果绝对是错误的。
30.把一个基本数据类型转为字符串,对象点toString()是最快的方法,对象点valueOf(数据)次之,
数据+""最慢
如,想把Integer i转为字符串类型,有三种方式:
(1) ()
(2) (i)
(3) i+""
下面测试
public static void main(String[] args) {
int loopTime = 50000;
Integer i = 0;
long startTime = ();
for(int j = 0 ;j < loopTime;j++) {
String str = (i);
}
("():"+(()- startTime) +"ms");
startTime = ();
for(int j = 0;j < loopTime;j++) {
String str = ();
}
("():"+(()- startTime) +"ms");
startTime = ();
for(int j = 0 ;j < loopTime;j++) {
String str = i + "";
}
("i+\"\":"+(()- startTime) +"ms");
}
结果:
():11ms;
():5ms;
i + "":25ms;
原理是:
(1) ()方法调用了()方法,但是
在调用前先做了一次空判断;
(2) ()是直接调用;
(3) i + ""是使用了StringBuilder实现,先用了append方法拼接,在用
toString()获取字符串