web-dev-qa-db-fra.com

Quelle est la bonne façon de gérer une exception NumberFormatException lorsqu'elle est attendue?

Je suis dans cette situation où j'ai besoin d'analyser un String dans un int et je ne sais pas quoi faire avec le NumberFormatException. Le compilateur ne se plaint pas quand je ne l'attrape pas, mais je veux juste m'assurer que je gère correctement cette situation.

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        i = 0;
    }
    return i;
}

Je veux simplement simplifier mon code comme ça. Le compilateur n'a pas de problème avec ça, mais le thread meurt sur le NumberFormatException.

private int getCurrentPieceAsInt() {
    int i = 0;
    i = Integer.parseInt(this.getCurrentPiece());
    return i;
}

Google CodePro veut que je consigne l'exception d'une manière ou d'une autre, et je reconnais qu'il s'agit de la meilleure pratique.

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        i = 0;
        e.printStackTrace();
    }
    return i;
}

Je veux que cette méthode renvoie 0 Lorsque la pièce actuelle n'est pas un nombre ou ne peut pas être analysée. Quand je n'attrape pas explicitement le NumberFormatException, n'attribue-t-il pas la variable i? Ou existe-t-il une valeur par défaut que Integer.parseInt() renvoie?

Le style général dit que si j'attrape une exception, je dois la connecter quelque part. Je ne veux pas l'enregistrer. Il est normal que cette exception soit levée parfois, ce qui ne me convient pas non plus. Cependant, je ne trouve pas de fonction qui me dira si Integer.parseInt() lèvera une exception. Donc, mon seul plan d'action semble être de simplement l'appeler et de saisir l'exception.

javadoc pour parseInt n'aide pas beaucoup.

Voici les questions spécifiques que j'aimerais savoir:

  • Existe-t-il une méthode que je peux appeler qui me dira si Integer.parseInt() lancera un NumberFormatException avant de l'appeler? Ensuite, je n'aurais aucun problème à enregistrer cela, car cela ne devrait jamais se produire.
  • Si je ne saisis tout simplement pas l'exception, le précieux ne sera-t-il pas affecté? Ensuite, je vais simplement l'initialiser à la valeur que je veux quand ce n'est pas un nombre et ne pas attraper l'exception.
  • Existe-t-il un moyen de marquer l'exception de manière explicite que je m'en fiche? Je pense que ce serait quelque chose de similaire à AWTEvent.consume(). Si c'est le cas, je le ferai pour que Google CodePro ne le considère pas comme "non connecté".
18
Erick Robertson
  • Existe-t-il une méthode que je peux appeler qui me dira si Integer.parseInt () lèvera une exception NumberFormatException avant de l'appeler? Ensuite, je n'aurais aucun problème à enregistrer cela, car cela ne devrait jamais se produire.

Malheureusement non. Du moins pas dans le noyau Java API. Il est facile d'en écrire un, cependant - il suffit de modifier le code ci-dessous.

  • Si je ne saisis tout simplement pas l'exception, le précieux ne sera-t-il pas affecté? Ensuite, je vais simplement l'initialiser à la valeur que je veux quand ce n'est pas un nombre et ne pas attraper l'exception.

Si vous n'attrapez pas l'exception, la pile se déroulera jusqu'à ce qu'elle atteigne un bloc catch qui la gérera, ou elle se déroulera complètement et arrêtera le thread. La variable ne sera en fait pas affectée mais ce n'est pas exactement ce que vous voulez.

  • Existe-t-il un moyen de marquer l'exception de manière explicite que je m'en fiche? Je pense que ce serait quelque chose de similaire à AWTEvent.consume (). Si c'est le cas, je le ferai pour que Google CodePro ne le considère pas comme "non connecté".

Il peut y avoir un moyen de dire à CodePro d'ignorer cet avertissement particulier. Certes, avec des outils comme FindBugs et Checkstyle, vous pouvez désactiver les avertissements dans des emplacements spécifiques. (EDIT: @Andy a indiqué comment procéder.)

Je soupçonne que ce que vous voulez, c'est quelque chose comme le paquet Commons Commons mentionné par @daveb. Il est assez facile d'écrire une telle fonction:

int parseWithDefault(String s, int def) {
    try {
        return Integer.parseInt(s);
    }
    catch (NumberFormatException e) {
        // It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input.
        return def;
    }
}
13
Cameron Skinner

Il y a NumberUtils.toInt (String, int) in commons lang qui fera exactement ce que vous voulez.

NumberUtils.toInt("123", 42) ==> 123
NumberUtils.toInt("abc", 42) ==> 42
9
daveb
* Is there a way to mark the exception somehow explicitly that I don't care about it? I'm thinking this would be something similar to AWTEvent.consume(). If so, then I will do this so that Google CodePro doesn't see this as "unlogged".

Oui, vous pouvez désactiver localement une règle d'audit CodePro pour une ligne de code:

http://code.google.com/javadevtools/codepro/doc/features/audit/locally_disabling_audit_rules.html

Cela dit, il n'est pas nécessairement nécessaire d'inclure la journalisation des diagnostics dans chaque bloc de capture d'exception. Parfois, la meilleure action consiste à suivre un cours par défaut. Parfois, c'est pour interagir avec l'utilisateur. Ça dépend.

3
Andy Thomas

Créez votre propre méthode pratique pour une utilisation actuelle et future:

public static int parseInt(final /*@Nullable*/ String s, final int valueIfInvalid) {
    try {
        if (s == null) {
            return valueIfInvalid;
        } else {
            return Integer.parseInt(s);
        }
    } catch (final NumberFormatException ex) {
        return valueIfInvalid;
    }
}

Existe-t-il une méthode que je peux appeler qui me dira si Integer.parseInt () lèvera une exception NumberFormatException avant de l'appeler? Ensuite, je n'aurais aucun problème à enregistrer cela, car cela ne devrait jamais se produire.

Pas que je sache. Gardez à l'esprit que s'il y en avait, vous finirez probablement par analyser la valeur deux fois (une fois pour valider et une fois pour l'analyser). Je comprends que vous voulez éviter l'exception, mais dans ce cas, cela attrape l'exception est l'idiome standard dans Java et il n'en fournit pas un autre (du moins que je sache).

Si je ne saisis tout simplement pas l'exception, le précieux ne sera-t-il pas affecté? Ensuite, je vais simplement l'initialiser à la valeur que je veux quand ce n'est pas un nombre et ne pas attraper l'exception.

Vous devez attraper l'exception (même si elle ne fait rien) ou elle échappera au bloc et vomira à travers la pile.

Existe-t-il un moyen de marquer l'exception de manière explicite que je m'en fiche? Je pense que ce serait quelque chose de similaire à AWTEvent.consume (). Si c'est le cas, je le ferai pour que Google CodePro ne le considère pas comme "non connecté".

Je n'en connais aucun. J'utiliserais la méthode de commodité ci-dessus (j'ai quelque chose de similaire dans une petite collection d'utilitaires généraux dont je dispose pour tous mes projets).

Je ne l'enregistrerais pas si c'est vraiment une condition normale que vous gérez. Je ne connais pas Google CodePro, mais j'espère qu'il existe un moyen de supprimer l'avertissement, par exemple une sorte d'annotation/mot-clé @SuppressWarnings ("xxx").


Edit: Je voulais signaler ces commentaires dans les commentaires ci-dessous

Cette approche ne gère toujours pas l'exception. C'est une mauvaise forme d'attraper une exception et de ne rien en faire. C'est pourquoi je recherche une meilleure solution

.

... L'exception (la situation) est gérée en retournant la valeur indiquée Si Invalide. La "mauvaise forme" vous faites référence à la mauvaise pratique d'écrire aveuglément et sans réfléchir) des blocs catch vides et ne jamais revenir en arrière pour vraiment considérer et traiter le cas. Si la situation d'exception est considérée et fait la bonne chose pour la situation ( même si la bonne chose est de faire rien ), alors vous avez "géré" l'exception.

1
Bert F

Vous devez attraper l'exception comme vous le faites. C'est ennuyeux, mais la meilleure approche.

Il n'y a pas de méthode Java API qui retournera 0 lorsque la chaîne n'est pas un entier valide.

Lorsque la chaîne n'est pas un int, une exception sera levée de sorte que votre variable int ne sera pas définie, sauf si vous interceptez l'exception comme vous le faites.

0
Marcus Leon

Votre premier bloc de code est correct. i ne sera pas implicitement converti en 0 lorsqu'une exception se produit et vous devez intercepter cette exception. Régler i sur 0 dans catch est correct; bien que vous puissiez simplement remplacer i = 0; avec return 0;. Vous ne pouvez pas éviter la gestion des exceptions dans ce cas.

Pour clarifier, vous pouvez utiliser ceci:

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        // log that an exception occured if it's needed
        return 0;
    }
    return i;
}
0
darioo

Si ce n'est pas clair comment vous devez le gérer depuis le getter, vous ne devriez pas l'attraper et laisser l'appelant s'en occuper à la place. Si vous savez comment le gérer, vous devez le faire. L'enregistrement peut ne pas être nécessaire ou très utile dans ce cas.

La journalisation d'une exception est plus utile si vous ne savez pas comment gérer l'exception et que vous la laissez à la personne qui lit les journaux.

0
Peter Lawrey

Comme d'autres l'ont mentionné, il n'y a pas de noyau intégré Java API que vous pouvez appeler pour valider un entier, mais vous pouvez utiliser la classe Character pour valider votre entrée - sans en utilisant la gestion des exceptions. Par exemple:

package com.example.parseint;

public class ValidateIntExample {
    public static boolean isInteger(String s) {
        if (s == null) {
            return false;
        }

        s = s.trim();

        if (s.length() == 0) {
            return false;
        }

        int start = 0;
        if (s.charAt(0) == '-') { // handle negative numbers
            if (s.length() == 1) {
                return false;
            }
            else {
                start = 1;
            }
        }

        for (int i = start; i < s.length(); i++) {
            if (! Character.isDigit(s.charAt(i))) {
                return false;
            }
        }

        return true;
    }
}

En fait, parseInt utilise lui-même Character.isDigit en interne, que vous pouvez vérifier dans le code source JRE. (Désolé, j'aurais inclus la méthode parseInt ici, mais je ne sais pas si je suis autorisé par les termes de la licence.) Si vous utilisez Eclipse et que vous avez le code source JRE attaché à votre projet, vous pouvez cliquer avec le bouton droit sur la méthode Integer.parseInt dans votre code et cliquez sur Ouvrir la déclaration.

0
rob