43 votes

Appel à la méthode de statique java.text.DateFormat déconseillé?

Je reçois une erreur Find Bugs - appel à la méthode de statique java.text.DateFormat et je ne connais pas la raison pour laquelle ce n'est pas bon / conseillé de faire ces choses ci-dessous.

 private static final Date TODAY = Calendar.getInstance().getTime();
private static final DateFormat yymmdd = new SimpleDateFormat("yyMMdd"); 

private String fileName = "file_" + yymmdd.format(TODAY);
 

82voto

Rob Hruska Points 39151

DateFormats ne sont pas thread-safe, ce qui signifie qu'ils maintiennent une représentation interne de l'etat. Leur utilisation dans un contexte statique peut donner quelques jolis bugs étranges si plusieurs threads accèdent à la même instance simultanément.

Ma suggestion serait de faire vos variables locales à l'endroit où vous êtes en utilisant, au lieu d'en faire des propriétés statiques de la classe. Il semble que vous pourriez faire quand vous êtes à l'initialisation de la classe, de sorte que vous pouvez le faire dans le constructeur:

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);
    }
    ...
}

Et si vous avez besoin d'utiliser le formateur dans plusieurs endroits, vous pourriez juste faire le patron static final et de créer un nouveau local DateFormat en cas de besoin:

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
    }
}

Le FindBugs de la documentation pour la question dit:

Comme la JavaDoc unis, DateFormats sont intrinsèquement dangereuses pour multithread utiliser. Le détecteur a trouvé un appel à une instance de DateFormat qui a été obtenu par l'intermédiaire d'un champ statique. Cette regarde suspectes.

Pour plus d'informations, voir le Soleil Bug #6231579 et le Soleil Bug #6178997.

Et la javadoc pour DateFormat suggère:

Les formats de Date ne sont pas synchronisés. Il est recommandé de créer des format instances pour chaque thread. Si plusieurs threads accèdent à un format en même temps, elle doit être synchronisée à l'externe.

Jack Leow réponse a également un bon point sur la sémantique de votre statique utilisation de "aujourd'HUI".

En aparté, j'en ai déjà vu cela se produire dans un environnement de production, et c'est très confus chose à déboguer à la première; ainsi, dans mon expérience, la FindBugs avertissement est en fait une suggestion utile (contrairement à certains autres l'analyse statique des règles, qui semblent parfois être tâtillon).

15voto

ScArcher2 Points 22118

Commons Lang possède un objet FastDateFormat qui est thread-safe. Cependant, il ne fait que le formatage, pas l'analyse.

Si vous pouvez utiliser commons-lang, cela pourrait bien fonctionner pour vous.

 private static final Date TODAY = Calendar.getInstance().getTime();
private static final FastDateFormat yymmdd = FastDateFormat.getInstance("yyMMdd");

private String fileName = "file_" + yymmdd.format(TODAY);
 

4voto

Michael Borgwardt Points 181658

Êtes-vous sûr que ce n'est pas

 private static final DateFormat yymmdd = new SimpleDateFormat("yyMMdd"); 
 

? C'est ce que le message d'erreur indique.

Je pense que ce qu'il vise est le fait que DateFormat n'est pas sûr pour les threads, donc avoir une instance comme champ statique indique des conditions de course potentielles.

4voto

Jack Leow Points 11081

Je ne suis pas sûr si FindBugs se plaint à ce sujet, mais un problème que je vois avec votre code, c'est que vous êtes à la définition d' TODAY comme un niveau de classe (statique), constant (final) de la variable. Ce communique l'intention que vous souhaitez TODAY à ne jamais changer (je ne crois pas que c'est le cas, depuis java.util.Les Dates sont mutables, mais c'est une autre histoire).

Pensez à ce qui arrive si l'application s'exécute pendant plusieurs jours? TODAY (sauf si vous le mettez à jour) sera référencement du jour où la demande a commencé, non pas de la date. Êtes-vous sûr que c'est ce que vous vouliez dire?

Cela peut ne pas être un bug dans votre code à tout, mais l'intention n'est pas claire, et je pense que peut être ce FindBugs est de se plaindre.

0voto

Pointy Points 172438

Ce n'est pas thread-safe, pour une chose.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X