6
votes

Évitez les blocs de capture vides lorsque vous attendez une exception


5 commentaires

"Aucun but comme aucune exception, une impression d'une parseexception pourrait être lancée par le bloc d'essai" Il pourrait y avoir un nullpointexception , en fonction de l'endroit où daturling "/ code> vient.


Désolé, je n'ai pas inclus cela dans mon code, mais il y a un chèque de pointeur nul avant cela.


Votre commentaire selon lequel "le bloc de capture est simplement là-bas, alors le bloc d'essai aurait quelque chose après" semble en arrière. Si vous ne vouliez pas non plus un attraper ou un enfin , vous ne devez pas nécessiter ou vouloir un essayer , non plus. Pour autant que je puisse déterminer, le bloc est là pour la raison habituelle: vous voulez attraper (certaines) exceptions.


"Je pourrais placer ce qui suit dans le bloc de capture:" Ne pas sur-attraper des exceptions: tout ce que vous devez gérer est parseexception . Ensuite, si un RunTimeException est lancé, qui sera propagé; et le compilateur garantit qu'aucune exception vérifiée sauf parseexception est lancée. Donc, c'est juste un moyen compliqué d'obtenir fondamentalement le même comportement.


Je vois. J'avais à l'origine un enregistreur dans le bloc de capture et je pensais peut-être que je pourrais peut-être vous débarrasser de tout ce qui ne faisait aucune exception qui a été jetée nulle part. Je vais juste garder un enregistreur là-bas.


7 Réponses :


0
votes

vous peut faire cela. Mais à mon avis (qui est partagé par un grand nombre d'autres développeurs de logiciels professionnels), des blocs de capture vides sont un anti-motif. Vous avez rencontré un cas exceptionnel dans votre code; Pourquoi l'ignorer? Cela signifie que vous avez une entrée incorrecte / inutilisable. Qui mérite une attention , n'est-ce pas d'accord?

Alors, oui , vous pouvez le faire. Mais vraiment, vraiment Demandez-vous, voulez-vous? Ou préférez-vous faire quelque chose de plus intelligent avec la mauvaise contribution que de la jeter silencieusement. Permettez-moi de vous donner ce bit de conseil: faites-vous vous-même (et quelqu'un d'autre qui travaillera avec votre code) la courtoisie d'au moins la journalisation des données exceptionnelles. Ne vous connectez pas simplement l'exception; Essayez de capturer ce qui était faux / exceptionnel avec l'état de votre application dans votre relevé de journal. Dans votre cas, je vous recommanderais de connecter l'enregistrement de la chaîne de date d'échec.

Enfin, si vous voulez omettre purement le bloc-catch ... Eh bien, vous ne pouvez pas aller de côté ignorer l'exception. Vous pouvez inclure une exception une déclaration sur votre prototype de méthode. Mais même alors, quiconque utilise votre API devra l'attraper. C'est juste une partie de la façon dont les exceptions vérifiées fonctionnent en Java.


4 commentaires

Ma question est de demander comment éviter cela, ne pas demander si c'est bon ou non.


@Photometricstereo Vérifiez le dernier paragraphe de ma réponse. Vous pouvez éviter d'écrire un Catch -BLOCK dans votre code, au coût de l'attente de quelqu'un d'autre pour l'attraper. C'est le seul moyen. Il fait partie des spécifications de Dateformat pour lancer une exception vérifiée (ParseException, spécifique) si la chaîne est imparable. Les spécifications de langue empêchent de les ignorer tout à fait.


Vous ne pouvez pas omettre un bloc de capture. Un essai doit être suivi d'au moins un attrape ou un final .


@Photométométricstereo qui est vrai. J'aurais dû être un peu plus verbeux, peut-être. Quand je dis que vous pouvez omettre la prise, je veux dire que vous omettez entièrement toute la structure d'essais.



2
votes

Votre code va bien. Il est intentionnel et raisonnable dans ce cas de ne prendre aucune mesure lorsque le SimpleDateDeformat code> jette un parseexception code>. La seule chose que je ferais différemment est d'insérer un commentaire documentaire à cet effet:

for (String format : formats)
{
    try
    {
        return new SimpleDateFormat(format).parse(dateString);
    }
    catch (ParseException e) {
        // The string does not conform to the trial format.
        // Just try the next format, if any.
    }
}


0 commentaires

1
votes

Si vous voulez éviter le bloc Essayer / Catch, il est possible, mais cela augmente certainement la taille du code. Le plus gros problème que j'ai avec des blocs de capture vides non moqués est qu'ils laissent la question de "je voulais dire //do: vérifier les exceptions ou non?" L'odeur de code que s'applique vraiment, imo, s'il n'a aucun sens de le faire de cette façon, c'est-à-dire si vous analysez de voir si quelque chose est un nombre, plutôt que d'utiliser une méthode ISnumber.

Vous pouvez créer une méthode explicite conçue. Pour vérifier si cela peut être analysé, puis renvoyer la valeur si elle est analyable. p> xxx pré>

puis appliquer p>

for (String format : formats)
{
    SimpleDateFormat format = new SimpleDateFormat(format);
    if(isParseable(dateString, format))
        return format.parse(dateString);
}
return null;


1 commentaires

Vous pouvez avoir isparsible (ou équivalent) renvoyer un en option , vous n'avez donc pas à l'analyser deux fois.



0
votes

Vous dites que vous n'aimez pas l'interface fournie par SimpleDateFormat . Votre seul choix consiste à envelopper cette interface dans une autre qui fournit l'interface que vous recherchez. E.g., xxx


0 commentaires

1
votes

Lorsque vous êtes en train de formater une date en essayant un format après un autre, c'est raisonnable que vous aurez un tas d'exceptions, propagez-leur serait inutile, même les voir même, n'est pas utile la plupart du temps. Le seul changement que je ferais consisterait à enregistrer l'exception au niveau de débogage ou de trace (défini ci-dessous où vous auriez votre journalisation normale lors de l'exécution du code dans le développement), donc au cas où vous souhaitiez revenir et examiner ce qui allait revenir sur vous devrez seulement changer la configuration de la journalisation. xxx


0 commentaires

2
votes

Toutes les réponses données jusqu'à présent, disons que vous devez vivre avec une exception capturée, mais Il existe des moyens d'éviter les exceptions sur tout strong>. Je démontre deux façons, une fois avec SimpleDateDeformat Code> -api et un avec l'utilisation de ma bibliothèque TIME4J .

SimpleDateFormat H2>
private static final MultiFormatParser<Moment> MULTI_FORMAT_PARSER;

static {
    String[] formats =
        {
               "yyyy-MM-dd'T'HH:mm:ss.SSSX", 
               "yyyy-MM-dd'T'HH:mm:ss.SSS-HH:mm",
               "EEE MMM dd HH:mm:ss Z yyyy"
        };

    List<ChronoFormatter<Moment>> formatters = 
        Arrays.stream(formats)
            .map(pattern -> 
                ChronoFormatter.ofMomentPattern(
                    pattern,
                    PatternType.CLDR,
                    Locale.ENGLISH,
                    Timezone.ofSystem().getID()))
            .collect(Collectors.toList());
    MULTI_FORMAT_PARSER = MultiFormatParser.of(formatters);
}

public static java.util.Date parse(String input) {
      ParseLog plog = new ParseLog();
      Moment m = MULTI_FORMAT_PARSER.parse(input, plog);
      if (plog.isError()) {
         // log an error message based on plog.getErrorMessage()
         return null; // or throw an exception
      } else {
         return TemporalType.JAVA_UTIL_DATE.from(m); // converted to old API
      }
}


3 commentaires

Merci pour la réponse, je vais explorer les méthodes que vous avez mentionnées. En outre, je vais changer mes formats de date. Je dois avoir le 'z' dans un parce que je reçois parfois ce type de date: 2016-07-15t08: 32: 53.689Z .


@Photométricstereo the iso-text "2016-07-15t08: 32: 53.689Z" signifie vraiment "2016-07-15t08: 32: 53.689 + 00: 00" (zéro décalage de UTC). Par conséquent, vous devez définir Timezone.gettimeZone ("GMT") sur votre SimpleDateDeformat Pour ce cas et ne s'appuie pas sur votre fuseau horaire système (qui correspond à la valeur par défaut).


@Photométométricstereo Si vous souhaitez utiliser SimpleDateDormat et êtes sur Java-7, vous pouvez également utiliser le symbole de motif "x" qui peut interpréter correctement le "Z" littéral.



0
votes

J'utiliserais quelque chose comme org.apache.commons.lang3.time.datetutils.ParseDate (ou parseDateStrictement si vous devez correspondre à l'ensemble du modèle). Il faut une liste de modèles possibles. Jetez un coup d'œil à cet exemple:

Date d = DateUtils.parseDate("23/10/2014T12:34:22", 
        new String[] {"yyyy/MM/dd'T'HH:mm:ss",
            "dd/MM/yyyy'T'HH:mm:ss"});

System.out.println(d);


0 commentaires