Comment savoir quelle variable est le coupable dans le bloc try?

Dans un certain bloc try, j’ai deux variables Ssortingng qui peuvent provoquer NumberFormatException lorsque j’utilise Integer.parseInt(ssortingng1) et Integer.parseInt(ssortingng2) . La question est, si catch une exception, comment savoir quelle chaîne est le fauteur de troubles? Je dois obtenir le nom de la variable du fauteur de troubles.

Voici un exemple de code:

 public class test { public static void main(Ssortingng[] args) { try { Ssortingng ssortingng1 = "fdsa"; Ssortingng ssortingng2 = "fbbbb"; Integer.parseInt(ssortingng1); Integer.parseInt(ssortingng2); } catch (NumberFormatException e) { e.printStackTrace(); } } } 

Et la méthode e.printStackTrace() ne me dit pas le nom de la variable; ça me dit juste le contenu du fauteur de troubles.

java.lang.NumberFormatException: Pour la chaîne d’entrée: “fdsa” à java.lang.NumberFormatException.forInputSsortingng (NumberFormatException.java:65) à l’adresse java.lang.Integer.parseInt (Integer.java:580) à l’adresse java.lang.Integer. parseInt (Integer.java:615) à test.main (test.java:9) à sun.reflect.NativeMethodAccessorImpl.invoke0 (méthode native) à sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) à sun.reflect .DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) à java.lang.reflect.Method.invoke (Method.java:498) à l’adresse com.intellij.rt.execution.application.AppMain.main (AppMain.java:147)

Processus terminé avec le code de sortie 0

La raison pour laquelle j’ai besoin de connaître le nom de la variable est que je dois informer l’utilisateur de ce qui se passe. Par exemple, indiquez à l’utilisateur que ssortingng1 est incorrect en utilisant

 System.out.println(troubleMakerName + "is wrong!") 

Dans mes exigences, l’utilisateur doit saisir

 fd=(fileName,maxLength,minLength) 

Je vais ensuite parsingr la chaîne d’entrée et créer des réponses. J’aimerais donc vérifier si maxLength et minLength lanceront NumberFormatException . Dans ce cas, si minLength a quelque chose qui ne va pas, alors je dois demander à l’utilisateur que le minLength est faux.

Vous avez un problème XY .

Vous ne voulez pas lire le nom de la variable réelle. Vous voulez être en mesure de valider les entrées et de donner des messages d’erreur raisonnables à votre utilisateur.

 Ssortingng fileName, maxLengthInput, minLengthInput; int maxLength, minLength; List errors = new ArrayList<>(); try { maxLength = Integer.parseInt(maxlengthInput); } catch (NumberFormatException nfe) { errors.add("Invalid input for maximum length, input is not a number"); } try { minLength = Integer.parseInt(minlengthInput); } catch (NumberFormatException nfe) { errors.add("Invalid input for minimum length, input is not a number"); } // show all error strings to the user 

Ne pas lancer les exceptions directement, mais les collecter, vous permet de notifier à l’utilisateur toutes les entrées non valides à la fois (peut-être de mettre en surbrillance les champs associés avec la couleur rouge) au lieu de les soumettre à nouveau. est également faux.

Au lieu de Ssortingngs, vous pouvez utiliser votre propre structure de données contenant des informations sur le champ concerné, etc., mais cela devient rapidement hors de scope. L’essentiel est: utilisez deux blocs try-catch et vous pouvez différencier le champ par défaut.

Si plus d’intrants sont impliqués, vous pouvez le transformer en boucle.

Utilisez 2 blocs séparés pour parsingr deux entrées pour chaque variable. Ensuite, générez le message de vérification de la santé mentale à l’intérieur de chaque bloc catch .

  Ssortingng ssortingng1 = "fdsa"; Ssortingng ssortingng2 = "fbbbb"; try { Integer.parseInt(ssortingng1); } catch (NumberFormatException e) { e.printStackTrace(); **//Please provide a valid integer for ssortingng1** } try { Integer.parseInt(ssortingng2 ); } catch (NumberFormatException e) { e.printStackTrace(); **//Please provide a valid integer for ssortingng2** } 

Je voudrais écrire parseInt propre méthode parseInt :

 public static int parseInt(Ssortingng s, Supplier supplier) { try { return Integer.parseInt(s); } catch (NumberFormatException e) { throw (RuntimeException)supplier.get().initCause(e); } } 

Comme je le sais, nous ne pouvons pas lire un nom de variable par reflection, alors je passe simplement un littéral Ssortingng la place:

 parseInt(ssortingng1, () -> new NumberFormatException("ssortingng1")); 

Je vais laisser la réponse d’origine et fournir une version qui a été discutée dans les commentaires. Mais pour le moment, je ne comprends pas pourquoi un fournisseur est excessif.

 public static int parseInt(Ssortingng s, Ssortingng message) { try { return Integer.parseInt(s); } catch (NumberFormatException e) { throw (NumberFormatException)new NumberFormatException(message).initCause(e); // throw new IllegalArgumentException(message, e); } } 

Son appel ressemble à

 parseInt(ssortingng1, "ssortingng1"); 

Avant d’effectuer l’opération, vous pouvez écrire une simple fonction isInteger () qui peut vous renvoyer une valeur booléenne. Une bonne implémentation peut être trouvée sur ce sujet. Cela utilise la base de la valeur et itère si c’est un int et est très pratique. Déterminer si une chaîne est un entier dans Java Un simple si conditionnel peut alors trouver quelle valeur est falsifiée dans l’argument

Il suffit d’utiliser un autre try try pour l’autre déclaration

 public class test { public static void main(Ssortingng[] args) { Ssortingng ssortingng1 = "fdsa"; Ssortingng ssortingng2 = "fbbbb"; try { Integer.parseInt(ssortingng1); } catch (NumberFormatException e) { System.out.println("ssortingng1 is the culprit"); e.printStackTrace(); } try { Integer.parseInt(ssortingng2); } catch (NumberFormatException e) { System.out.println("ssortingng2 is the culprit"); e.printStackTrace(); } } } 

Vous pouvez créer une méthode avec un try / catch qui retourne la valeur que vous atsortingbuez ou imprime à la console en cas de problème, de cette manière vous pouvez prendre en charge autant de variables que vous en avez besoin avec un seul try / catch les variables qui causent un problème.

 public class test { public static void main(Ssortingng[] args) { Ssortingng ssortingng1 = returnSsortingng("fdsa", "ssortingng1"); Ssortingng ssortingng2 = returnSsortingng("fbbbb", "ssortingng2"); } private ssortingng returnSsortingng(Ssortingng input, Ssortingng varName) { Ssortingng str = ""; try { str = input; Integer.parseInt(str); } catch (NumberFormatException e) { System.out.println("Error processing " + varName); } return str; } } 

Je suis surpris que personne n’ait proposé quelque chose comme ceci:

 public class test { public static void main(Ssortingng[] args) { Ssortingng errorContext; try { Ssortingng ssortingng1 = "fdsa"; Ssortingng ssortingng2 = "fbbbb"; errorContext = "ssortingng1"; Integer.parseInt(ssortingng1); errorContext = "ssortingng2"; Integer.parseInt(ssortingng2); } catch (NumberFormatException e) { System.out.println(errorContext + " is wrong!") e.printStackTrace(); } } } 

C’est une solution très simple – simpliste , diraient certains – mais elle est également assez claire et robuste.

Le sharepoint cette question – si je comprends bien – n’était pas de fournir une meilleure façon de convertir des chaînes en nombres entiers (même si elle existe), mais plutôt de trouver un moyen de dire non seulement ce qui a mal tourné dans un long bloc. , mais aussi là où ça s’est mal passé. Si l’objective est d’afficher un message d’erreur significatif pour l’utilisateur (suggérant idéalement ce qu’il faut faire plutôt que de simplement se plaindre que quelque chose ne va pas), il suffit bien sûr d’imprimer une trace de stack et de tenter chaque ligne de code. n’est pas une option attrayante non plus.

Vous devez éviter d’attraper des Runtime exceptions et utiliser un autre mécanisme pour identifier les erreurs. Dans votre cas, vous pouvez utiliser matcher et votre problème pourrait être écrit comme suit:

 public class test { private static final Pattern pattern = Pattern.comstack("\\d+"); public static void main(Ssortingng[] args) { Ssortingng ssortingng1 = "fdsa"; Ssortingng ssortingng2 = "fbbbb"; if (pattern.matcher(ssortingng1).matches()) { Integer.parseInt(ssortingng1); } else { //ssortingng1 is not an integer } ... } } 

Ou vous pourriez simplement écrire

 boolean errorInLineOne = !pattern.matcher(ssortingng1).matches(); ... 

C’est assez simpliste, mais voici ma solution.

 public class test { public static int tryParseInt(Ssortingng str) throws Exception { try { return Integer.parseInt(str); } catch(Exception e) { System.err.println("tryParseInt: couldn't parse '"+str+"'"); throw e; } } public static void main(Ssortingng[] args) { try { Ssortingng ssortingng1 = "fdsa"; Ssortingng ssortingng2 = "fbbbb"; tryParseInt(ssortingng1); tryParseInt(ssortingng2); } catch (NumberFormatException e) { e.printStackTrace(); } } }