上次面試的時(shí)候,免面試官問我java代碼優(yōu)化,雖然平時(shí)在實(shí)際開發(fā)中也有注意這方面的問題,但當(dāng)時(shí)就是沒回來上來,都怪平時(shí)沒注意總結(jié),所以今天就在這里總結(jié)。這里我還要提醒下那些新手,想學(xué)好一門技能,總結(jié)非常重要。好記性不如爛筆頭。好了廢話不多說了。
1.盡量減少對變量的重復(fù)計(jì)算
使用帶下標(biāo)的for循環(huán)時(shí),如下所示:
List<String> list = new ArrayList<>();
...
for(int i = 0; i < list.size(); i++) {
}
這種情況下,最好把對size的計(jì)算放到循環(huán)外,因?yàn)檫@樣每次遍歷都會(huì)計(jì)算一次,造成了不必要的浪費(fèi)。改成如下:
List<String> list = new ArrayList<>();
...
int size;
for(int i = 0; i < size = list.size(); i++) {
}
獲取方法參數(shù)的值時(shí),對值的獲取盡量只有一次(即,使用get()方法獲?。?。這樣做后你的參數(shù)引用只有一個(gè),維護(hù)更加方便。
2. 如果事先知道容器的容量,初始化時(shí)盡量指定它的初始容量(initialCapacity)
例如Map可以這樣指定
Map<String, Object> map = new HashMap<>(2);
3. 計(jì)算時(shí)盡量使用位運(yùn)算
例如對一個(gè)數(shù)乘/除一個(gè)偶數(shù),如下:
int a = 5;
int b = a * 4;
int c = a / 4;
改為:
int a = 5;
int b = a << 2; //右移兩位
int c = a >> 2;//左移兩位
4. int轉(zhuǎn)String,盡量使用String.valueOf();不要使用+ ""。+ ""在底層會(huì)使用StringBuilder的append()方法,最后調(diào)用toString()。這里貼上javap后的源碼:
@Test
public void test1() {
int a = 5;
String s = a + "";
}
javap -c 后的源碼:
public void test1();
Code:
0: iconst_5
1: istore_1
2: new #2 // class java/lang/StringBuilder
5: dup
6: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
9: iload_1
10: invokevirtual #4 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
13: ldc #5 // String
15: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
21: astore_2
22: return
還是做了很多操作的。接下來我們看看String.valueOf()方法:
@Test
public void test1() {
int a = 5;
String s = String.valueOf(a);
}
javap -c 后的源碼:
public void test1();
Code:
0: iconst_5
1: istore_1
2: iload_1
3: invokestatic #2 // Method java/lang/String.valueOf:(I)Ljava/lang/String;
6: astore_2
7: return
不多說了,很明顯的變化。
所以盡量使用String.valueOf()。
5. 對變量的聲明盡量放到條件語句內(nèi)(盡量采用懶加載的策略,即在需要的時(shí)候才創(chuàng)建)
public void printB(int a){
int b = 2;
if (a == 1) {
System.out.println(b);
}
}
這時(shí)的System.out.println(b);在a不等于1時(shí),是不會(huì)被執(zhí)行的,所以因該把b變量的聲明放到條件內(nèi)部,如下:
public void printB(int a){
if (a == 1) {
int b = 2;
System.out.println(b);
}
}
這個(gè)也很容易做到。
6. 使用equals比較時(shí),常量盡量放在equals前,這樣不容易出現(xiàn)NullPointException
7. 返回值位數(shù)組/列表時(shí),沒有值返回值,盡量不要返回null,而是返回空數(shù)組
這樣做的好處就是,調(diào)用方法不需要先判斷是否返回nul,代碼更簡潔,而且可以減少因?yàn)槭韬龆鸬目罩羔槷惓!?/p>
8. 對流的盡量使用帶資源的try
從jdk 1.7之后出現(xiàn)了帶資源的try語句。只要實(shí)現(xiàn)了AutoCloseable接口,都可以使用帶資源的try。這樣做的好處就是,不需要再顯示的調(diào)用close方法,也就不會(huì)出現(xiàn)因?yàn)橥浾{(diào)用而引起的資源為釋放。
9. 對變量的的聲明放到循環(huán)外
10. 對字符串的操作使用StringBuilder/StringBuffer(線程安全)
例如字符串的連接,不要使用 + "" +,使用加號(hào)連接,底層使用的是StringBuilder,每使用一次加號(hào)連接賦值,都會(huì)重新new一個(gè)StringBuilder。所以建議使用直接使用StringBuilder/StringBuffer(線程安全)。