不建议调用静态 java.text.DateFormat 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2409657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Call to method of static java.text.DateFormat not advisable?
提问by setzamora
I am receiving a Find Bugserror - call to method of static java.text.DateFormatand I don't know the reason why it's not good / advisable to be doing these things below.
我收到一个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);
采纳答案by Rob Hruska
DateFormats are not thread-safe, meaning that they maintain an internal representation of state. Using them in a static context can yield some pretty strange bugs if multiple threads access the same instance simultaneously.
DateFormats 不是线程安全的,这意味着它们维护状态的内部表示。如果多个线程同时访问同一个实例,在静态上下文中使用它们会产生一些非常奇怪的错误。
My suggestion would be to make your variables local to where you're using them instead of making them static properties of the class. It looks like you might be doing this when you're initializing the class, so you could do this in the constructor:
我的建议是让你的变量在你使用它们的地方是本地的,而不是让它们成为类的静态属性。看起来您在初始化类时可能会这样做,因此您可以在构造函数中执行此操作:
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);
}
...
}
And if you need to use the formatter in multiple places, you might just make the pattern static final
and create a new local DateFormat
when needed:
如果你需要在多个地方使用格式化程序,你可能只需要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
}
}
The FindBugs documentationfor the issue says:
该问题的FindBugs 文档说:
As the JavaDoc states, DateFormats are inherently unsafe for multithreaded use. The detector has found a call to an instance of DateFormat that has been obtained via a static field. This looks suspicous.
For more information on this see Sun Bug #6231579 and Sun Bug #6178997.
正如 JavaDoc 所述,DateFormats 对于多线程使用来说本质上是不安全的。检测器发现对通过静态字段获取的 DateFormat 实例的调用。这看起来很可疑。
有关这方面的更多信息,请参见 Sun Bug #6231579 和 Sun Bug #6178997。
And the javadoc for DateFormatsuggests:
而DateFormat的javadoc建议:
Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.
日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问一个格式,则必须在外部进行同步。
Hyman Leow's answeralso has a good point about the semantics of your static use of "TODAY".
Hyman Leow 的回答对您静态使用“TODAY”的语义也有一个很好的观点。
As an aside, I've actually seen this happen in a high-traffic production environment, and it's a very confusing thing to debug at first; so in my experience the FindBugs warning is actually a useful suggestion (unlike some other static analysis rules, which sometimes seem to be nitpicky).
顺便说一句,我实际上在高流量生产环境中看到了这种情况,而且一开始调试是一件非常令人困惑的事情;所以根据我的经验,FindBugs 警告实际上是一个有用的建议(不像其他一些静态分析规则,有时看起来很挑剔)。
回答by Pointy
It's not thread-safe, for one thing.
一方面,它不是线程安全的。
回答by Michael Borgwardt
Are you sure it's not
你确定不是
private static final DateFormat yymmdd = new SimpleDateFormat("yyMMdd");
? That's what the error message indicates.
? 这就是错误消息所指示的。
I think what it aims at is the fact that DateFormat
is not thread safe, so having an instance as a static field indicates potential race conditions.
我认为它的目标DateFormat
是不是线程安全的事实,因此将实例作为静态字段表示潜在的竞争条件。
回答by Bjorn J
I assume this is because format is not thread-safe?
我认为这是因为格式不是线程安全的?
(I have not seen what findbugs complain about, can you provide the warning text?)
(我还没有看到 findbugs 抱怨什么,你能提供警告文本吗?)
回答by Paul Tomblin
You can get this to go away by wrapping all the references to the DateFormat in a synchronize block - just make sure all calls are wrapped in the samesynchronize object!
您可以通过将所有对 DateFormat 的引用包装在一个同步块中来消除这种情况——只需确保所有调用都包装在同一个同步对象中!
回答by Hyman Leow
I'm not sure if FindBugs is complaining about this, but one problem I see with your code is that you're defining TODAY
as a class level (static), constant (final) variable. This communicates the intent that you want TODAY
to never change (I don't believe this is the case, since java.util.Dates are mutable, but that's another story).
我不确定 FindBugs 是否在抱怨这一点,但我在您的代码中看到的一个问题是您将定义TODAY
为类级别(静态)、常量(最终)变量。这传达了您不想TODAY
改变的意图(我不相信是这种情况,因为 java.util.Dates 是可变的,但那是另一回事了)。
Think about what happens if you application runs for multiple days? TODAY
(unless you update it) will be referencing the day the application was started, not the current date. Are you sure this is what you meant?
想想如果您的应用程序运行多天会发生什么?TODAY
(除非您更新它)将引用应用程序启动的日期,而不是当前日期。你确定这是你的意思吗?
This may not be a bug in your code at all, but the intent is not clear, and I believe that maybe what FindBugs is complaining about.
这可能根本不是您代码中的错误,但意图并不明确,我相信这可能是 FindBugs 所抱怨的。
回答by ScArcher2
Commons Langhas a FastDateFormatobject that is thread safe. It only does formatting though, not parsing.
Commons Lang有一个线程安全的FastDateFormat对象。它只做格式化,不做解析。
If you can use commons-lang this might work well for you.
如果您可以使用 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);
回答by Wim Deblauwe
An alternative that not has been mentioned is using ThreadLocal. See http://www.javacodegeeks.com/2010/07/java-best-practices-dateformat-in.htmlfor more info + performance comparison between the 3 options:
一个没有提到的替代方法是使用 ThreadLocal。请参阅http://www.javacodegeeks.com/2010/07/java-best-practices-dateformat-in.html了解更多信息 + 3 个选项之间的性能比较:
- Creating an instance each time
- Synchronising access
- Using ThreadLocal
- 每次创建一个实例
- 同步访问
- 使用线程本地
Example of using ThreadLocal:
使用 ThreadLocal 的示例:
private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyMMdd");
}
};
Usage:
用法:
DATE_FORMAT.get().format( TODAY )