Java代码中的一些小技巧,总有一个帮助到你

104 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


此贴不定时更新哦

  1. 在循环中不要新建引用,放到循环外建立,循环内使用,虽然对象是存在堆里面,但引用会压入栈,So......

  2. 同样是循环,在设立循环条件时,不要以重复访问对象为条件,缓存进栈,虽然是个小细节,养成习惯总是好的,例如:

	Object[] temp=new Object[1000];
	for(int i=0,n=temp.length;i<n;i++){
		......
	}
  1. 对于final的使用,在数组上其实很没意义,数组的引用不可再变,但是成员仍然可以变化,但是,此时数组内容也不会变,只不过变化的那个成员不再属于数组了而已,如例
	String str="old";
	final String[] temp={str};
	// a error
	// temp=new String[3];
	str=new String("new");
	/**
	 * now 
	 * temp[0]=="old"
	 * str=="new";
	 */

如上,

  1. 继续上面,对于经常使用的常量请加上final,JVM在运行时会缓存final变量,并且在多线程的共享不需要增加同步开销,不可变性相对就提高了安全性。

  2. 说到多线程,对于同步synchronized关键字,尽量使用同步代码块,不要同步方法,synchronized原理可以查阅相关文章,总之synchronized同步的代码越少越好。

  3. 如果仅仅是一个变量的同步请不要使用同步代码块,直接用volatile修饰变量即可。

  4. 继续线程安全,在我们平时码代码是时,除非明确要求使用线程安全类,不然别去使用,线程安全类就是增加了同步开销,以StringBuffer和StringBuilder为例,前者属于线程安全,但实际情况下我们使用需要线程安全的情况微乎其微(至少我没遇到),所以StringBuilder更为效率。

  5. 继续StringBuilder相关,在字符串拼接,不要直接使用+拼接,此种方法效率最差,而字符串的concat方法实质就是现分解为char数组,在复制重新生成字符串,效率只比+好一点,StringBuilder和StringBuffer通常选取前者最为拼接字符串的优先考虑。

  6. 接上面,String 重载了+ 和 +=,但是在字符串用+连接时,实质JVM运行也是编译了一个临时的StringBuilder来执行append,也就是说,即使你用了+,其实还是用的StringBuilder,只不过是由JVM代替了你使用而已。

  7. 在循环内除非必要,否则不要处理异常,原因在于异常基类Throwable中的public synchronized native Throwable fillInStackTrace(),如你所见,是个同步方法,当抛出异常捕捉后,就会进入同步块。

  8. 虽然try-catch用来处理业务流程看起来更好用,但是实际上catch是一个隐形的同步块,所以性能肯定比不上if-else

  9. 对于确定的死循环,for(;;)优于while(true),原因在于前者编译后执行的汇编代码更少,如例:

for(;;)

jmp	wmain+29h

while(true)

mov	eax,1
test eax,eax
je wmain+29h
jmp wmain+1Eh
  1. 在传统的大小判断上,尽量直接使用(x>y)而非(x-y>0),因为如果x=MAX或者MIN时,则会OOM。

  2. 接上,在大小判断上,如果比较值y是个确定的数,可以使用y-1代替x>=y(即x>y-1),同理使用y+1代替x<=y(即x<y+1),减少一次等于判断,但前提是比较值y是一个确定的数,否则参考13。

  3. foreach语法能够遍历任何实现了Iterable接口的类,但是foreach里不能对遍历的集合进行增删。

  4. 接上,map集合中的values,keySet.entrySet遍历时可以直接操作原map,因为这几个方法返回的是集合副本

// HashMap源码示例
public Collection<V> values() {
    Collection<V> vs = values;
    if (vs == null) {
        vs = new Values();
        values = vs;
    }
    return vs;
}
  1. 自从1.5提出泛型后,泛型就是一个编码离不开的工具,又爱又恨,泛型能够在编写父类接口及方法定义时突破一定的局限性,但成也萧何败也萧何,也是这种泛型机制,导致实际使用时(尤其时跨服务调用时)易出现ClassCaseException
  2. ThreadLocal使用完后一定要remove,不要觉得是弱引用就不在意,该OOM还是逃不掉。
  3. 如果能静下心来的话,看书的效率的确比视频高,视频为求细致和拉时长,会反复磨蹭,实在碰到搞不懂的问题,实际编码一次,查看源码,比视频理解起来更通透。