2010-05-01 2 views
14

Je veux demander pourquoi nous n'avons pas besoin d'ajouter un bloc try-catch à un RuntimeException alors que nous devrions le faire avec d'autres exceptions?Pourquoi nous ne devons pas ajouter try-catch à une exception RuntimeException?

Je veux dire comme:

public class Main { 
    public static void main(String[] args) { 
     throw new RuntimeException(); 
    } 
} 

Edit: quand je dis: throw new RuntimeException(); il est si clair qu'il ya une exception qui va se passer, alors pourquoi le compilateur n'interdit pas?

+6

Notez que 'RuntimeExceptions' sont généralement lancées lorsqu'une erreur de programmation/code est survenue. La solution est généralement juste en corrigeant le code. Vous ne devriez généralement pas les attraper. – BalusC

+0

Vraiment? Je crois que l'une des meilleures pratiques est de convertir l'exception vérifiée à l'exception non vérifiée que les attraper tous à un endroit pour afficher à l'utilisateur? – vodkhang

+0

@vodkhang Ce que j'essaie de dire est pourquoi le compilateur n'interdit pas un code quand il est clair qu'il y a une RuntimeException qui se produira. –

Répondre

25

C'est parce que c'est une non cochée exception. Il n'a pas besoin d'être explicitement déclaré ou attrapé. Voir aussi le Sun tutorial on the subject.

Mise à jour: en général, vous ne devez jeter un RuntimeException (de préférence un de ses subclasses énumérés dans le javadoc) pour signaler que l'appelant fait mal. C'est à dire. passer un argument null (puis lancer NullPointerException), ou un argument illégal (puis lancer IllegalArgumentException), ou la méthode est appelée au mauvais moment/état (puis lancer IllegalStateException), etcetera. L'appelant est censé réparer son code pour éviter cela. Par exemple. vérifier au préalable si l'argument n'est pas nul, ou si l'argument est au bon format/syntaxe, ou s'assurer que la méthode est appelée au bon moment. Si une situation spécifique doit déclencher une exception d'exécution et que vous ne pouvez pas utiliser l'une de ses sous-classes spécifiques, vous devez l'étendre et la documenter correctement dans javadoc de la nouvelle exception et dans la méthode appelante, par exemple ConfigurationException extends RuntimeException dans le cas où le code appelant n'a pas correctement configuré l'application/API avant utilisation. Cela devrait signaler suffisamment l'utilisateur final (l'autre développeur) pour agir en conséquence.

En résumé: doit identifier les problèmes récupérables par programme qui sont causés par des erreurs dans le flux de code ou la configuration (lire: les erreurs du développeur). Check Exceptions doit identifier les problèmes récupérables par programme qui sont causés par des conditions inattendues en dehors du contrôle du code (par exemple, arrêt de la base de données, erreur d'E/S de fichier, mauvaise entrée de l'utilisateur final, etc.). Errors doit identifier les problèmes irrécupérables par programme (par exemple, mémoire insuffisante, exception dans un initialiseur, etc.).

+0

mais quand je dis: "throw new RuntimeException();" il est si clair qu'il y a une exception qui se produira, alors pourquoi le compilateur n'interdit-il pas cela? –

+0

Il n'y a rien de moralement incorrect avec une exception. Les exceptions non contrôlées ne sont pas intentionnellement vérifiées. D'où le nom décoché. –

+0

@ M.H non ce n'est pas clair. Un exemple est la méthode List.add(), une implémentation normale de la liste, comme arraylist ne lancera jamais une exception UnsupportedOperationException, il n'est donc pas nécessaire qu'elle figure dans la signature d'exception. La méthode Collections.asUnmodifyableList() retournera une liste qui lancera une exception UnsupportedOperationException sur les appels à List.add. L'implémentation de List.add consiste seulement à lancer new UnsupportedOperationException. Avec seulement un objet de type Liste vous ne pouvez pas voir si l'exception sera levée et une liste normale ne devrait jamais la lancer. – josefx

2

RuntimeException, Error et leurs sous-classes ne sont spécifiquement pas vérifiées à la compilation - elles ne font pas partie du contrat formel de la méthode.

Voir le chapitre 11 dans JLS, Exceptions, en particulier 11.2, Vérification au moment de la compilation des exceptions.

2

Lets soutiennent cette façon. Que faire si NullPointerException a été conçu pour être une exception de compilation? Si cela avait été fait, le compilateur devait vérifier strictement si une variable est nulle ou non. Il n'y a aucun moyen que cela puisse être fait.

public void dummyMethod(Object obj){ 

} 

Ici, il n'y a aucun moyen pour le compilateur de vérifier si l'obj peut être nul ou non. Cependant, il doit y avoir une erreur/une exception doit être levée lorsque vous avez un scénario de pointeur nul.

+0

Voulez-vous prétendre qu'il introduirait une contrainte fondamentale si NullPointerException était une exception vérifiée? Je ne comprends pas l'exemple que vous fournissez? Il pourrait être parfaitement logique que la méthode accepte obj == null dans certaines implémentations. – aioobe

+0

Je voulais juste que vous pensiez en termes d'aspect de conception. C'est parfaitement logique d'avoir à la fois cochée et non cochée. Maintenant, pour que le compilateur vérifie ces règles, vous devrez en définir les 'types' dont RuntimeException est un et NullPointerException en est un type. Et la réponse à votre question est oui, c'est un problème lorsque NPE est vérifié. L'exemple que j'ai fourni est de dire que l'objet obj passé à la méthode peut être et ne peut pas être nul et que cette méthode n'a aucune idée à ce sujet. Un compilateur ne peut jamais vérifier de telles instances. – bragboy

1

Parce qu'il n'est pas interdit de lancer des exceptions d'exécution et vous n'avez pas à déclarer les exceptions d'exécution.Votre programme est un programme Java valide donc le compilateur n'a aucune raison de se plaindre.

1

Fondamentalement, une exception non interceptée est simplement un raccourci pour afficher un message et mettre fin à l'application.

Pourquoi auriez-vous besoin de faire cela? Dans certains cas, vous pouvez détecter que quelque chose a mal tourné, que certains fichiers ne se sont pas chargés, qu'une API est manquante, que certaines données sont corrompues pour une raison ou une autre, ou qu'un million d'autres choses sont erronées. Si vous ne lancez pas d'exception, l'application peut simplement tomber en panne à un autre point ou, dans le pire des cas, continuer à fonctionner pendant que l'erreur augmente, rendant le débogage beaucoup plus difficile.

Il est important de comprendre que l'on lève une exception car il y a une erreur, l'exception n'est pas l'erreur, c'est juste le messager.

+0

+1 merci réponse très utile –

2

par spécification de langage, exceptions non vérifiées sont pas vérifiées à la compilation ce qui signifie que le compilateur ne nécessite pas de méthodes pour attraper ou de préciser (avec un throws) eux. Les classes appartenant à cette catégorie sont détaillés dans la section 11.2 Compile-Time Checking of Exceptions du JLS:

Les exceptions non vérifiées des classes sont la classe RuntimeException et ses sous-classes, et la classe Error et ses sous-classes. Toutes les autres classes d'exception sont classes d'exceptions vérifiées. L'API Java définit un certain nombre de classes d'exceptions, cochées et non cochées. Des classes d'exceptions supplémentaires, cochées et non cochées, peuvent être déclarées par les programmeurs. Voir §11.5 pour une description de la hiérarchie des classes d'exceptions et de certaines classes d'exceptions définies par l'API Java et la machine virtuelle Java.

Donc, comme RuntimeException dans une exception non contrôlée, le compilateur ne vous force pas à le gérer. Si vous voulez forcer l'appelant d'un morceau de code à gérer une exception, utilisez une exception cochée (les sous-classes de Exception autres que RuntimeException sont toutes des classes d'exception vérifiées).

1

La plupart des réponses sur ce forum parlaient de la hiérarchie Exception et du compilateur Java, mais j'essaierais d'y répondre davantage du point de vue de la conception et pourquoi les choses ont peut-être été conçues comme ça.

Fondamentalement, lorsque vous appelez une fonction (ou écrire du code) une exception peut être jeté hors de celui-ci repose sur trois situations différentes:

  1. Basé sur une condition inévitable comme indisponibilité du réseau ou d'un fichier attendu manquant sur le système de fichiers.

  2. Sur la base d'un évitable, mais condition connue comme Integer.parseInt(String) peut jeter NumberFormatException si l'appelant passe une chaîne inconvertibles comme "Hello", mais l'appelant peut assurer la validation appropriées en place avant de passer dans une chaîne à la fonction et complètement faire disparaître avec la possibilité de générer l'exception. Un cas d'utilisation courant pourrait être la validation du champ de formulaire age sur une page Web avant de le transmettre aux couches plus profondes qui effectuent la conversion.

  3. Une condition connue ou inconnue tout moment une ligne de code peut lancer une exception dans votre code parce qu'il y avait une erreur que vous avez fait et n'a pas respecté les conditions d'erreur jusqu'à ce qu'il décollait dans la production, se produit généralement avec NullPointer Reference, IndexOutOfBounds etc, qui, si elle observé serait peut-être tomber dans la catégorie 2.

exceptions de la catégorie 1 sont généralement conçus comme Checked Exceptions parce qu'il a besoin de faire respecter la vérification des conditions d'erreur inévitables, et de faire valoir leurs solutions de repli. Par exemple, IOException est une exception vérifiée, car si vous ouvrez un fichier, il peut y avoir beaucoup de choses qui peuvent mal tourner (comme le fichier peut être supprimé, les permissions etc.) et la validation préalable peut être très lourde. Les exceptions du 2ème type sont généralement modélisées comme Unchecked Exceptions parce que vous pourriez avoir votre pré-validation en place et il pourrait être irritant d'être obligé d'utiliser essayer et attraper pour les situations que vous avez déjà pris en charge.

Les exceptions du 3ème type ne doivent pas être même généralement inquiétées parce que vous ne pouvez pas mettre la gestion des erreurs dans chaque déclaration de code d'application qui peut apparaître de façon inattendue. Mais parfois, vous pouvez placer un gestionnaire global, quelque part tout à fait dans la pile d'appels d'où presque tout le code d'application est exécuté et le gérer de manière générique afin que votre application ne plante pas en raison d'une erreur inattendue. Par exemple, si vous exécutez une application Web, vous pouvez configurer votre conteneur de servlet pour qu'il envoie un message générique 500 Internal Server Error pour toute erreur non gérée dans votre application. Ou, si vous exécutez une application Java autonome, vous pouvez conserver le contenu de votre main method dans un bloc try catch pour empêcher le blocage de l'application.

Questions connexes