J'ai vu ce sujet surgir parfois dans le passé, mais même après Googling À ce sujet , je ne peux toujours pas comprendre ce qui serait une bonne et élégante façon de faire face à cela, alors c'est ici.
Dis que j'ai du code qui jette différentes exceptions ... ... et comme nous pouvons le constater, je saisis ces exceptions et jette un nouveau dit que quelque chose s'est mal passé dans mon API. P> Ceci Il me semble un code trop répétitif, il suffit donc d'attraper un type d'exception et de gérer l'envelopper et de lancer une nouvelle. p> Dans ce cas, il reste bien plus simple, Mais la chose est que nous serions également attraper toutes les runtimédies. Compte tenu de cela, nous pourrions attraper-re-jeter la runtimédiexception afin que nous puissions éviter cela. P> c'est un peu volumineux mais cela fait l'affaire. Maintenant, il y a maintenant un autre petit problème sur la capture (exception e), que si mon API intérieur jette une autre myapIexception, elle serait également prise, enveloppée et jetée dans une autre myapIexception. Dans ce cas particulier, nous pourrions aussi attraper MyAPIException et le jeter. P> try {
/* some code that throws some exceptions */
} catch (RuntimeException e) {
throw e;
} catch (MyAPIException e) {
throw e;
} catch (Exception e) {
throw new MyAPIException("Something went wrong", e);
}
6 Réponses :
avoir plus d'un Plus, vous ne pouvez pas résoudre l'une des captures simples ou plusieurs captures. C'est plus d'une décision de jugement imo car il existe des exceptions qui sont fatales (comme dans l'ensemble du programme, doivent arrêter) à des types plus faciles à manipuler. P>
Je ne vois rien de mal au tout lorsque vous avez un tas de Un facteur supplémentaire qui décide que c'est la complexité de l'API. Parfois, j'avais écrit une API qui était modérément complexe et je devais faire face aux mêmes problèmes comme celui que vous avez présenté. J'avais écrit quelques exceptions personnalisées pour quelques méthodes. Je suis sûr que vous ne finirez pas de jeter des exceptions pour toute la méthode publique que l'API expose, mais il existe des endroits qu'ils sont inévitables. P>
Enfin, si vous sentez avoir trop d'exceptions personnalisées, un choix amer, vous pouvez avoir une seule exception avec des codes d'erreur clairement documentés. De cette façon, l'appelant peut gérer l'exception et traiter les codes d'erreur car il voit en forme. P> myapiException code>. Si vous avez toutes les exceptions comme
MyAPIException code>, il devient un peu difficile pour vous et pour les autres aussi à lire votre code. Nommer cela correctement serait aussi crucial. De plus, vous ne voulez pas toujours attraper et retirez-le. Si tel est le cas, déclarez simplement un
lance code> dans la signature de méthode. P>
lancers code> des clauses dans votre API. C'est une implémentation beaucoup plus chère. Alors, que si l'appelant doit gérer les exceptions que vous avez définies. Si une méthode dans votre API peut lancer une exception et que quelque chose doit être fait à ce sujet, l'appelant doit alors avoir à le gérer. Quoi qu'il en soit, votre documentation de cette exception particulière doit être claire afin de ne pas confondre l'appelant. P>
La chose est si je commence simplement à jeter toutes les autres exceptions, quelqu'un d'autre devrait faire face à toutes ces exceptions et je ne pense pas que c'est très agréable d'avoir une méthode qui jette de nombreux types d'exceptions. De plus, si je devais avoir un type d'exception à chaque exception enveloppée, ce serait simplement idiot ... pourquoi pas simplement le jeter? (Et maintenant nous avons une récursion)
Eh bien, dans ce cas, je veux juste le montrer à l'utilisateur de cette API que quelque chose a mal tourné et qu'il ne pouvait pas être terminé, il peut y faire face à cela dans un simple bloc de capture (capture (myapiException e)) au lieu d'attraper Plusieurs types d'exceptions ou devoir faire face à ce même problème de capture présenté ici. Si l'utilisateur souhaitait connaître la raison pour laquelle il a échoué, il peut toujours regarder la cause à l'intérieur de l'exception. Je pense que quelque chose comme ça serait un moyen d'API Natre, mais comme vous l'avez dit, cela pourrait être une décision de jugement. Des pensées?
Comme vous l'avez souligné, nous pourrions également avoir beaucoup d'exceptions spécifiques pour chaque cas, mais l'OMI, il serait sage de rendre toutes ces exceptions s'étendre d'une seule exception dans votre API. Comme ceci, l'utilisateur pouvait gérer chaque cas (captures spécifiques) ou une prenant tout (prenez l'exception principale d'API) en fonction de ses besoins.
en Java 7, vous pourrez faire quelque chose comme
try { /* some code that throws these exceptions */ } catch (NoSuchAuthorityCodeException , FactoryException, MismatchedDimensionException , TransformException e) { throw new MyAPIException("Something went wrong", e); }
Ouais, j'en ai entendu parler, mais la chose est, à l'entreprise que je travaille, nous utilisons toujours Java5 (!!!), et j'aimerais faire quelque chose d'élégant au sein de Java5 ou Java6 pour la question
Depuis que vous êtes coincé avec Java5 et que vous utilisez une exception exclusive, pourquoi ne pas mettre toute cette logique d'exception dans la classe d'exception.
USEAGE P>
class MyAPIException extends Exception { private MyAPIException ( String message , Throwable cause ) { super ( message , cause ) ; } private static void myAPIException ( Exception cause ) throws MyAPIException { throw new MyAPIException ( "Something Went Wrong" , cause ) ; } public static void handle ( Exception e ) throws MyAPIException { try { throw ( e ) ; } catch ( RuntimeException cause ) { throw cause ; } catch ( MyAPIException cause ) { throw cause ; } catch ( NoSuchAuthorityCodeException cause ) // repeat for other exceptions { myAPIException ( cause ) ; } catch ( Exception cause ) // this should not happen { assert false ; // or log it or throw a RuntimeException ... somehow signal that programming logic has failed } } }
Je ne veux vraiment pas attraper la runtimédiexception et l'apiezexception
Ce serait bien si vous mettez un exemple d'utilisation.
@Pablo Cabrera J'ai ajouté un exemple d'utilisation. Il lancera la runtimédiexception et la myapIexception. Je mettais tout la méthode statique S dans la classe MyAPIException. Vous pouvez appeler cela de votre code avec un simple essai / attraper.
+1. Je ne pense pas que ce soit la meilleure solution, mais c'est une approche très intéressante.
Ce n'est pas très flexible ... Et si je voudrais jeter cette exception sur un autre contexte (ce que je fais)? Devrais-je gérer ces autres exceptions aussi? Devrais-je coder une "poignée" spécifique pour chaque utilisation?
@Pablo Cabrera Si vous gérez toujours des exceptions de la même manière, vous pouvez utiliser une méthode (par exemple la poignée) pour le faire - éliminer le code dupliqué. Modifiez la méthode de la poignée donnée en ajoutant des blocs de capture pour toutes les exceptions que vous souhaitez prendre en charge. Si vous ne gérez pas toujours des exceptions de la même manière, cela est moins utile.
@emory, mais j'aurais alors le même nombre de "captures" que j'avais dans le premier exemple ...
Tout dépend de ce que vous voulez faire. Si tout ce que vous voulez faire, c'est lancer une nouvelle myException ("quelque chose mal tourné", e); code> puis une capture tout va faire. P>
Comme je l'ai dit auparavant, je ne veux pas attraper runtimédiexception ou myapIexception ... RTFQ
Ok gars, voici ce que je suis venu avec ... ce n'est pas si élégant mais je pense que c'est un peu mieux que d'avoir diverses captures.
Tout d'abord, nous avons une classe abstraite appelée ExceptionnelHandler forte >. P> try {
/* some code that throws these exceptions */
} catch (Exception e) {
new ExceptionHandler<MyAPIException>() {
@Override
protected void handler(Throwable t) throws MyAPIException {
throw new MyAPIException("Something went wrong", t);
}
}.
catches(MismatchedDimensionException.class).
catches(NoSuchAuthorityCodeException.class).
catches(FactoryException.class).
catches(TransformException.class).
handle(e);
return null;
}
L'idée est très bonne. (1) Utilisez ISAssignABLEDFROM au lieu d'IsInstance de. (2) Je ne comprends pas vraiment la méthode GetGenericClass. Je pense que ce serait plus propre de la classe Exceptionnel Herdler juste pour avoir une instance de classe
(5) Remplacez le non gré par «ASSTERTE FAUX:« Exception non confondue »;« Je n'aime pas le non-fiancé ». Si l'exceptionnelle doit être instanciée correctement, il ne devrait pas y avoir de pas de non pas. La présence de la non-andhandexception indique donc une erreur de programmation.
Maintenant, je pense que je comprends mieux ce que tu veux. Donc, j'ai une autre réponse ci-dessous.
ci-dessous est une autre approche et un exemple d'utilisation. La classe MyAPIException a une méthode de la poignée. La méthode de la poignée traitera toute exception.
Lorsque vous testez votre code, exécutez-le avec des assertions activées. En production, exécutez-la avec des assertions désactivées. P>
class Usage
{
public static void main ( String [ ] args ) throws MyAPIException
{
try
{
switch ( Integer . parseInt ( args [ 0 ] ) )
{
case 1 :
throw new RuntimeException ( ) ;
case 2 :
throw new SQLException ( ) ;
case 3 :
throw new MyAPIException ( null ) ;
case 4 :
throw new IOException ( ) ;
}
}
catch ( Exception cause )
{
System . out . println ( cause . getMessage ( ) ) ;
System . out . println ( cause . getCause ( ) ) ;
MyAPIException . handle ( cause , IOException . class ) ;
}
}
}