有许多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