2010-07-13 7 views
94

Ces instructions de code sont-elles équivalentes? Y a-t-il une différence entre eux?try/catch versus throws Exception

private void calculateArea() throws Exception { 
     ....do something 
    } 

private void calculateArea() { 
     try { 
      ....do something 

     } catch (Exception e) { 
      showException(e); 
     } 
    } 
+2

Pas vraiment une réponse, mais vous pourriez être intéressé par article de Ned Batchelder [Exceptions dans la forêt tropicale] (http://nedbatchelder.com/text/exceptions-in-the-rainforest.html), qui aide à expliquer les cas généraux où un style ou l'autre doit être préféré. –

+1

au lieu d'avoir "showException (e)" dans la capture, demandiez-vous si vous aviez "throws e" dans la capture à la place (ou ne pas avoir le try/catch du tout)? – MacGyver

Répondre

116

Oui, il y a une énorme différence - ce dernier avale l'exception (le montrant, il est vrai), alors que le premier va laisser se propager. (Je suppose que showException ne le réenvoie pas.)

Donc, si vous appelez la première méthode et que "faire quelque chose" échoue, l'appelant devra gérer l'exception. Si vous appelez la deuxième méthode et que "faire quelque chose" échoue, l'appelant ne verra pas d'exception ... ce qui est généralement une mauvaise chose, à moins que ait vraiment géré l'exception, corrigé ce qui était faux, et généralement fait en sorte que calculateArea a atteint son but.

Vous serez en mesure de le dire, parce que vous ne pouvez pas appeler la première méthode sans soit attraper Exception vous ou déclarant que votre méthode pourrait jeter aussi.

+10

Lorsque vous mentionnez que «à moins qu'il ne gère vraiment l'exception», c'est un excellent point. Je pensais juste ajouter qu'attraper "Exception" elle-même conduit rarement à une "gestion" intelligente de l'exception réelle qui est la raison pour laquelle les gens vous recommandent d'attraper l'exception la plus spécifique possible. –

+16

+1.Parce que Jon Skeet a besoin de plus de réputation. Oh, et la réponse était bonne aussi. –

13

Oui. La version qui déclare throws Exception nécessitera le code appelant pour gérer l'exception, tandis que la version qui le gère explicitement ne le fera pas.

dire simplement:

performCalculation(); 

contre le déplacement de la charge de gérer l'exception à l'appelant:

try { 
    performCalculation(); 
catch (Exception e) { 
    // handle exception 
} 
11

premier throws Exception, de sorte que l'appelant doit gérer le Exception. Le second attrape et gère Exception en interne, de sorte que l'appelant n'a pas besoin de gérer les exceptions.

+0

Donc, en un mot, je devrais toujours utiliser le second. Ai-je raison? Le premier est en fait une méthode qui est utilisée dans différents points du programme. C'est pourquoi j'ai décidé de rassembler les instructions pour une utilisation ultérieure, mais après avoir fait cela, je réalise maintenant que T faisait une grosse erreur .. – carlos

+7

Non, les deux modèles sont nécessaires. Si votre méthode peut gérer l'exception, utilisez le second modèle, sinon, utilisez le premier pour notifier l'appelant. –

+0

La version que vous utilisez dépend de vos besoins - essentiellement à quel niveau devez-vous gérer cette exception. L'appelant doit être codé en conséquence. Si un appelant appelait la première version et que vous remplacez la définition de la méthode par la deuxième version, votre code d'appelant sera obligé de gérer l'exception car il s'agit d'une exception vérifiée. – samitgaur

4

Oui, il y a une grande différence entre eux. Le premier bloc de code, vous passez l'exception au code appelant. Dans le deuxième bloc de code, vous le manipulez vous-même. La méthode correcte dépend entièrement de ce que vous faites. Dans certains cas, vous voulez que votre code gère l'exception (si un fichier n'est pas trouvé et que vous voulez le créer, par exemple) mais dans d'autres, vous voulez que le code appelant gère l'exception (un fichier n'est pas trouvé et ils doivent en spécifier un nouveau ou le créer).

De manière générale, vous ne souhaitez pas non plus intercepter une exception générique. Au lieu de cela, vous ne voulez attraper que ceux spécifiques, tels que FileNotFoundException ou IOException parce qu'ils peuvent signifier des choses différentes.

1

Je suppose que par "identique" vous parlez de comportement.

Un comportement d'une fonction peut être déterminée par:

1) Valeur retournée

2) des exceptions lancées

3) des effets secondaires (i.Dans ce cas, la première méthode propage n'importe quelle exception, tandis que la seconde ne renvoie aucune exception vérifiée et avale aussi la plupart des exceptions non cochées, ce qui fait que le comportement est différent.

Toutefois, si vous garantissez que « faire quelque chose » ne lève jamais une exception, le comportement sera identique (bien que le compilateur exigera l'appelant à gérer l'exception, dans la première version)

--edit Du point de vue de la conception API, les méthodes sont complètement différentes dans leur contrat. En outre, lancer classe Exception n'est pas recommandé. Essayez de lancer quelque chose de plus spécifique pour permettre à l'appelant de mieux gérer l'exception.

3

Il y a un scénario particulier où nous ne pouvons pas utiliser les lancers, nous devons utiliser try-catch. Il existe une règle "Une méthode surchargée ne peut lancer aucune exception supplémentaire autre que celle lancée par sa classe parente". S'il y a une exception supplémentaire qui devrait être traitée en utilisant try-catch. Considérez cet extrait de code. Il y a une simple classe de base

package trycatchvsthrows; 

public class Base { 
    public void show() 
    { 
     System.out.println("hello from base"); 
    } 
} 

et il est dérivé classe:

package trycatchvsthrows; 

public class Derived extends Base { 

    @Override 
    public void show() { 
     // TODO Auto-generated method stub 
     super.show(); 

     Thread thread= new Thread(); 
     thread.start(); 
     try { 
      thread.sleep(100); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     // thread.sleep(10); 
     // here we can not use public void show() throws InterruptedException 
     // not allowed 
    } 
} 

Quand nous devons appeler Thread.sleep(), nous sommes obligés d'utiliser try-catch, ici nous ne pouvons pas utiliser :

public void show() throws InterruptedException 

car la méthode substituée ne peut pas lancer d'exceptions supplémentaires.

+0

Je crois que tout le monde n'est pas au courant de cette mise en garde. Bien pointé. – ivanleoncz

0

L'appelant de cette méthode devra soit attraper cette exception, soit déclarer qu'elle doit être renvoyée dans sa signature de méthode.

private void calculateArea() throws Exception { 
     // Do something 
    } 

Dans l'exemple de bloc try-catch ci-dessous. L'appelant de cette méthode n'a pas à s'inquiéter de la gestion de l'exception car elle a déjà été prise en charge.

private void calculateArea() { 
    try { 
     // Do something 

    } catch (Exception e) { 
     showException(e); 
    } 
} 
0

Plusieurs fois, vous souhaitez que l'appelant gère l'exception. Imaginons que l'appelant appelle une méthode qui appelle une autre méthode qui appelle une autre méthode, au lieu que chaque méthode gère l'exception, vous pouvez simplement la gérer à l'appelant. Sauf si vous voulez faire quelque chose dans l'une des méthodes lorsque cette méthode échoue.

1

Si vous jetiez une exception, la méthode de l'enfant (qui remplace ce) doit gérer l'exception

exemple:

class A{ 
public void myMethod() throws Exception{ 
//do something 
} 
} 

A a=new A(); 
try{ 
a.myMethod(); 
}catch Exception(e){ 
//handle the exception 
} 
Questions connexes