37 votes

String to Int in java - Probablement de mauvaises données, besoin d'éviter les exceptions

Étant donné que Java n'a pas de type nullable, ni de TryParse(), comment gérer la validation des entrées sans lever d'exceptions ?

Comme d'habitude :

String userdata = /*value from gui*/
int val;
try
{
   val = Integer.parseInt(userdata);
}
catch (NumberFormatException nfe)
{
   // bad data - set to sentinel
   val = Integer.MIN_VALUE;
}

Je pourrais utiliser une expression rationnelle pour vérifier s'il est possible de l'analyser, mais cela semble également entraîner beaucoup de frais généraux.

Quelle est la meilleure pratique pour gérer cette situation ?

EDIT : Justification : Il y a eu beaucoup de discussions sur l'OS à propos de la gestion des exceptions, et l'attitude générale est que les exceptions ne devraient être utilisées que pour des scénarios inattendus. Cependant, je pense qu'une mauvaise entrée utilisateur est PRÉVUE, et non rare. Oui, c'est vraiment un point académique.

Autres modifications :

Certaines des réponses démontrent exactement ce qui ne va pas avec l'OS. Vous ignorez la question posée et répondez à une autre question qui n'a rien à voir avec celle-ci. La question ne porte pas sur la transition entre les couches. La question n'est pas de savoir ce qu'il faut retourner si le nombre est indéchiffrable. Pour autant que vous le sachiez, val = Integer.MIN_VALUE ; est exactement la bonne option pour l'application d'où provient cet extrait de code totalement hors contexte.

28voto

J'ai demandé s'il y avait des bibliothèques d'utilitaires open source qui avaient des méthodes pour faire ce parsing pour vous et la réponse est oui !

De Langage Apache Commons :

// returns defaultValue if the string cannot be parsed.
int i = org.apache.commons.lang.math.NumberUtils.toInt(s, defaultValue);

De Google Guava :

// returns null if the string cannot be parsed.
Integer i = com.google.common.primitives.Ints.tryParse(s);

Il n'est pas nécessaire d'écrire vos propres méthodes pour analyser les nombres sans lancer d'exceptions.

17voto

Pour les données fournies par l'utilisateur, Integer.parseInt est généralement la mauvaise méthode car elle ne prend pas en charge l'internationnalisation. Le site java.text est votre ami (verbeux).

try {
    NumberFormat format = NumberFormat.getIntegerInstance(locale);
    format.setParseIntegerOnly(true);
    format.setMaximumIntegerDigits(9);
    ParsePosition pos = new ParsePosition(0);
    int val = format.parse(str, pos).intValue();
    if (pos.getIndex() != str.length()) {
        // ... handle case of extraneous characters after digits ...
    }
    // ... use val ...
} catch (java.text.ParseFormatException exc) {
    // ... handle this case appropriately ...
}

16voto

Steve B. Points 23227

C'est à peu près tout, bien que le fait de renvoyer MIN_VALUE soit un peu discutable, à moins que vous ne soyez sûr que c'est la bonne chose à utiliser pour ce que vous utilisez essentiellement comme code d'erreur. Au minimum, je documenterais le comportement du code d'erreur, cependant.

Il peut également être utile (en fonction de l'application) d'enregistrer les entrées erronées afin de pouvoir les retracer.

11voto

asterite Points 3218

Quel est le problème avec votre approche ? Je ne pense pas que cette façon de procéder nuise aux performances de votre application. C'est la façon correcte de procéder. Ne pas optimiser prématurément .

6voto

Grant Wagner Points 14085

Je suis sûr que c'est de mauvais goût, mais j'ai un ensemble de méthodes statiques sur une classe Utilities qui font des choses telles que Utilities.tryParseInt(String value) qui renvoie 0 si la chaîne n'est pas séparable et Utilities.tryParseInt(String value, int defaultValue) qui vous permet de spécifier une valeur à utiliser si parseInt() lance une exception.

Je crois qu'il y a des moments où retourner une valeur connue sur une mauvaise entrée est parfaitement acceptable. Un exemple très artificiel : vous demandez à l'utilisateur une date au format AAAAMMJD et il vous donne une mauvaise entrée. Il peut être parfaitement acceptable de faire quelque chose comme Utilities.tryParseInt(date, 19000101) ou Utilities.tryParseInt(date, 29991231); en fonction des exigences du programme.

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