有許多Java模因讓我很煩,部分是因為它們總是一個壞主意,但主要是因為人們在找到更好的替代方案后的幾年里仍在繼續使用它們。
使用StringBuffer代替StringBuilder
從2004年開始,用于StringBuffer的Javadoc
從JDK 5版本開始,該類已經添加了一個等效類,該類旨在供單線程StringBuilder使用。 通常應優先使用StringBuilder類,因為它支持所有相同的操作,但它卻更快,因為它不執行同步,因此它優先于此類使用。
StringBuilder不僅是一個更好的選擇,而且本來可以使用同步StringBuffer的情況非常罕見,這與以往不同,這是一個好主意。
說你有代碼
// run in two threads
sb.append(key).append("=").append(value).append(", ");
每個追加都是線程安全的,但是可以隨時釋放該鎖,這意味著您可以
key1=value1, key2=value2,
key1=key2value1=, value2,
key1key2==value1value2, ,
更糟糕的是,為了提高效率,JIT和JVM將試圖在兩次調用之間保持鎖定。 這意味著您可以擁有可以通過所有測試并可以在生產環境中使用多年的代碼,但是很少中斷,這可能是由于升級JVM所致。
使用DataInputStream讀取文本
另一個常見的模因是在讀取以下模板中的文本時使用DataInputStream(三個行,兩個閱讀器在同一行),我懷疑有一個原始代碼被復制了。
FileInputStream fstream = new FileInputStream("filename.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
這是不好的,原因有三個
- 由于BufferedReader的緩沖性質,您可能會傾向于使用in來讀取無法使用的二進制文件。 (我已經看到了這個嘗試)
- 同樣,您可能會相信DataInputStream在不這樣做的情況下會在此處做一些有用的事情
- 有一種更短的方法是正確的。
BufferedReader br = new BufferedReader(new FileReader("filename.txt"));
// or with Java 7.
try (BufferedReader br = new BufferedReader(new FileReader("filename.txt")) {// use br
}
使用雙重檢查鎖定創建單例
首次使用Double Checked鎖定時,這是一個壞主意,因為JVM不安全地支持此操作。
// Singleton with double-checked locking:
public class Singleton {private volatile static Singleton instance;private Singleton() { }public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
問題在于,直到Java 5.0為止,這通常是可行的,但在內存模型中無法保證。 有一個更簡單的選項是安全的,不需要顯式鎖定。
// suggested by Bill Pugh
public class Singleton {// Private constructor prevents instantiation from other classesprivate Singleton() { }/*** SingletonHolder is loaded on the first execution of Singleton.getInstance()* or the first access to SingletonHolder.INSTANCE, not before.*/private static class SingletonHolder {public static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}
這仍然很冗長,但是可以正常工作,不需要顯式鎖定,因此可以更快。
在Java 5.0中,當他們修復內存模型以安全地處理雙重鎖定時,他們還引入了枚舉,從而為您提供了更為簡單的解決方案。
約書亞·布洛赫(Joshua Bloch)在他的第二本書《有效的Java》中聲稱“單元素枚舉類型是實現單例的最佳方法”
使用枚舉,代碼看起來像這樣。
public enum Singleton {INSTANCE;
}
這是延遲加載的,線程安全的,沒有顯式的鎖并且簡單得多。
參考: Java模因在Vanilla Java博客上拒絕死于我們的JCG合作伙伴 Peter Lawrey。
翻譯自: https://www.javacodegeeks.com/2012/08/java-memes-which-refuse-to-die.html