2010-03-15 13 views
4

J'écris un analyseur pour les fichiers CSV, et parfois je reçois NumberFormatException. Existe-t-il un moyen facile d'imprimer la valeur d'argument qui a provoqué l'exception?Comment est-ce que je peux imprimer la valeur d'argument qui a provoqué l'exception dans Java?

Pour le moment dois-je beaucoup blocs try-catch qui ressemblent à ceci:

String ean; 
String price; 

try { 
    builder.ean(Long.parseLong(ean)); 
} catch (NumberFormatException e) { 
    System.out.println("EAN: " + ean); 
    e.printStackTrace(); 
} 

try { 
    builder.price(new BigDecimal(price)); 
} catch (NumberFormatException e) { 
    System.out.println("Price: " + price); 
    e.printStackTrace(); 
} 

Je voudrais pouvoir écrire quelque chose comme:

try { 
    builder.ean(Long.parseLong(ean)); 
} catch (NumberFormatException e) { 
    e.printMethod(); // Long.parseLong() 
    e.printArgument(); // should print the string ean "99013241.23" 
    e.printStackTrace(); 
} 

Y at-il façon que je puisse au moins améliorer mon code? Et faire ce genre d'impression/journalisation plus programmatique?

MISE À JOUR: J'ai essayé de mettre en œuvre ce qui a répondu Joachim Sauer, mais je ne sais pas si je suis tout droit ou si je pouvais l'améliorer. S'il vous plaît donnez-moi quelques commentaires. Voici mon code:

public class TrackException extends NumberFormatException { 
    private final String arg; 
    private final String method; 

    public TrackException (String arg, String method) { 
     this.arg = arg; 
     this.method = method; 
    } 

    public void printArg() { 
     System.err.println("Argument: " + arg); 
    } 

    public void printMethod() { 
     System.err.println("Method: " + method); 
    } 
} 

La classe Wrapper:

import java.math.BigDecimal; 
public class TrackEx { 
    public static Long parseLong(String arg) throws TrackException { 
     try { 
      return Long.parseLong(arg); 
     } catch (NumberFormatException e) { 
      throw new TrackException(arg, "Long.parseLong"); 
     } 
    } 

    public static BigDecimal createBigDecimal(String arg) throws TrackException { 
     try { 
      return new BigDecimal(arg); 
     } catch (NumberFormatException e) { 
      throw new TrackException(arg, "BigDecimal.<init>"); 
     } 
    } 
} 

Exemple d'utilisation:

try { 
    builder.ean(TrackEx.createBigDecimal(ean)); 
    builder.price(TrackEx.createBigDecimal(price)); 
} catch (TrackException e) { 
    e.printArg(); 
    e.printMethod(); 
} 

EDIT: Même question mais pour .NET: In a .net Exception how to get a stacktrace with argument values

+1

en ce qui concerne votre solution: c'est fondamentalement, mais je changerais deux choses: 1.) Rendre possible la cause (en appelant 'initCause()' dans le constructeur puisque le 'NumberFormatException' n'a pas de constructeur pour cette) et 2.) remplacez les méthodes 'printArg()' et 'printMethod()' par des getters appropriés, car l'impression sur 'System.err' n'est peut-être pas ce que le développeur veut faire avec ces valeurs. –

+0

@Joachim Sauer: Merci beaucoup, c'est un bon conseil! – Jonas

Répondre

9

Vous pouvez facilement mettre en œuvre de telles informations détaillées sur des exceptions personnalisées tions, mais la plupart des exceptions existantes ne fournissent pas beaucoup plus qu'un message de détail et une exception causale. Par exemple, vous pouvez inclure tous vos besoins d'analyse numérique dans une classe d'utilitaires qui attrape NumberFormatException et lance une exception personnalisée à la place (en prolongeant éventuellement NumberFormatException).

Un exemple où on effectue la quelques informations supplémentaires via l'exception est SQLException qui a un getErrorCode() et un procédé getSQLState().

+0

Je ne sais pas Si je vous ai bien compris, mais j'ai ajouté ma mise en œuvre dans la question. S'il vous plaît donnez-moi un commentaire Si je me suis trompé. Quoi qu'il en soit, ça fonctionne bien. – Jonas

3

Créez une méthode telle que private parse (String value, int type) qui effectue le travail d'analyse réel, y compris la gestion des exceptions et la journalisation.

parse(ean, TYPE_LONG); 
parse(price, TYPE_BIG_DECIMAL); 

TYPE_ est juste quelque chose à dire la méthode comment il doit analyser la valeur.

1

Semblable à une autre suggestion, vous pouvez extraire Long.parseLong(ean) dans sa propre méthode (soit en privé dans la classe ou public sur un autre type de classe utilitaire).

Cette nouvelle méthode traiterait toute logique personnalisée ET vous pourriez le tester de manière isolée. Yay!