我收到一个Find Bugs错误 - 调用静态java.text.DateFormat的方法,我不知道为什么在下面做这些事情不好/可取的原因.
private static final Date TODAY = Calendar.getInstance().getTime();
private static final DateFormat yymmdd = new SimpleDateFormat("yyMMdd");
private String fileName = "file_" + yymmdd.format(TODAY);
Run Code Online (Sandbox Code Playgroud)
Rob*_*ska 82
DateFormats不是线程安全的,这意味着它们维护状态的内部表示.如果多个线程同时访问同一个实例,在静态上下文中使用它们会产生一些非常奇怪的错误.
我的建议是将变量置于您使用它们的位置,而不是使它们成为类的静态属性.在初始化类时,您可能正在执行此操作,因此您可以在构造函数中执行此操作:
public class MyClass {
private String fileName;
public MyClass() {
final Date today = Calendar.getInstance().getTime();
final DateFormat yymmdd = new SimpleDateFormat("yyMMdd");
this.fileName = "file_" + yymmdd.format(TODAY);
}
...
}
Run Code Online (Sandbox Code Playgroud)
如果您需要在多个位置使用格式化程序,您可以在需要时static final
创建模式并创建新的本地化DateFormat
:
public class MyClass {
private static final String FILENAME_DATE_PATTERN = "yyMMdd";
public void myMethod() {
final DateFormat format = new SimpleDateFormat(FILENAME_DATE_PATTERN);
// do some formatting
}
}
Run Code Online (Sandbox Code Playgroud)
该问题的FindBugs文档说:
正如JavaDoc所述,DateFormats对于多线程使用本质上是不安全的.检测器找到了一个通过静态字段获得的DateFormat实例的调用.这看起来很可疑.
有关这方面的更多信息,请参阅Sun Bug#6231579和Sun Bug#6178997.
而DateFormat的javadoc建议:
日期格式未同步.建议为每个线程创建单独的格式实例.如果多个线程同时访问格式,则必须在外部进行同步.
Jack Leow的答案对于静态使用"TODAY"的语义也有一个很好的观点.
另外,我实际上已经看到这种情况发生在高流量的生产环境中,最初调试是一件非常令人困惑的事情.所以根据我的经验,FindBugs警告实际上是一个有用的建议(不像其他一些静态分析规则,有时似乎是挑剔的).
ScA*_*er2 15
Commons Lang有一个线程安全的FastDateFormat对象.它只进行格式化,而不是解析.
如果你可以使用commons-lang,这可能适合你.
private static final Date TODAY = Calendar.getInstance().getTime();
private static final FastDateFormat yymmdd = FastDateFormat.getInstance("yyMMdd");
private String fileName = "file_" + yymmdd.format(TODAY);
Run Code Online (Sandbox Code Playgroud)
尚未提及的替代方案是使用 ThreadLocal。有关更多信息以及 3 个选项之间的性能比较,请参阅http://www.javacodegeeks.com/2010/07/java-best-practices-dateformat-in.html :
使用 ThreadLocal 的示例:
private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyMMdd");
}
};
Run Code Online (Sandbox Code Playgroud)
用法:
DATE_FORMAT.get().format( TODAY )
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
34670 次 |
最近记录: |