Try / catch contre jette Exception

117

Ces instructions de code sont-elles équivalentes? Y a-t-il une différence entre eux?

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

private void calculateArea() {
    try {
        ....do something
    } catch (Exception e) {
        showException(e);
    }
}
carlos
la source
3
Ce n'est pas vraiment une réponse, mais vous pourriez être intéressé par l'article de Ned Batchelder, Exceptions in the Rainforest , qui aide à expliquer les cas généraux où un style ou l'autre doit être préféré.
Daniel Pryden
1
au lieu d'avoir "showException (e)" dans le catch, demandiez-vous si vous aviez plutôt "throws e" dans le catch (ou si vous n'aviez pas du tout le try / catch)?
MacGyver

Réponses:

146

Oui, il y a une énorme différence - ce dernier avale l'exception (le montrant, certes), alors que le premier la laissera se propager. (Je suppose que showExceptioncela ne le rejette 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 du tout d'exception ... ce qui est généralement une mauvaise chose, à moins d' showExceptionavoir véritablement géré l'exception, corrigé ce qui n'allait pas et généralement assuré qui calculateAreaa atteint son objectif.

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

Jon Skeet
la source
12
Lorsque vous mentionnez que «à moins qu'il ne gère véritablement l'exception», c'est un excellent point. J'ai juste pensé que j'ajouterais qu'attraper "Exception" lui-même conduit rarement à une "gestion" intelligente de l'exception réelle, ce qui est la raison pour laquelle les gens vous recommandent de capturer l'exception la plus spécifique possible.
Bill K
17
+1. Parce que Jon Skeet a besoin de plus de réputation. Oh, et la réponse était bonne aussi.
Jonathan Spiller
20

Tout d'abord throws Exception, l'appelant doit gérer le Exception. Le deuxième attrape et gère en Exceptioninterne, de sorte que l'appelant n'a pas à faire de gestion d'exception.

samitgaur
la source
Donc, en un mot, je devrais toujours utiliser le second. Ai-je raison? La première est en fait une méthode qui est utilisée à différents points du programme. C'est pourquoi j'ai décidé de regrouper les instructions pour une utilisation ultérieure, mais après avoir fait cela, je réalise maintenant que T faisait une grosse erreur ..
carlos
9
Non, les deux modèles sont nécessaires. Si votre méthode peut gérer l'exception, utilisez le deuxième modèle, sinon utilisez le premier pour notifier l'appelant.
Andreas Dolk
La version que vous utilisez dépend de vos besoins - essentiellement à quel niveau avez-vous besoin pour 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 méthode par la deuxième version, votre code appelant sera forcé de gérer l'exception car il s'agit d'une exception vérifiée.
samitgaur
16

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

c'est-à-dire simplement:

performCalculation();

vs transférer le fardeau de la gestion de l'exception à l'appelant:

try {
    performCalculation();
catch (Exception e) {
    // handle exception
}
Lyle
la source
6

Oui, il y a une grande différence entre eux. Dans le premier bloc de code, vous transmettez l'exception au code appelant. Dans le deuxième bloc de code, vous le gérez 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 est introuvable et ils doivent en spécifier un nouveau ou en créer un).

De manière générale également, vous ne voulez pas intercepter une exception générique. Au lieu de cela, vous voudrez n'en attraper que certains, comme FileNotFoundExceptionou IOExceptionparce qu'ils peuvent signifier des choses différentes.

Chris Thompson
la source
3

Il existe un scénario particulier où nous ne pouvons pas utiliser de lancers, nous devons utiliser try-catch. Il existe une règle "Une méthode surchargée ne peut pas lever d'exception supplémentaire autre que celle que sa classe parent lance". S'il y a une exception supplémentaire qui doit être gérée à l'aide de try-catch. Considérez cet extrait de code. Il existe une classe de base simple

package trycatchvsthrows;

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

et sa classe dérivée:

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 on doit appeler thread.sleep () on est obligé d'utiliser try-catch, ici on ne peut pas utiliser:

 public void show() throws InterruptedException

car la méthode surchargée ne peut pas lever d'exceptions supplémentaires.

Arjun Thakur
la source
Je pense que tout le monde n'est pas au courant de cette mise en garde. Bien pointu.
ivanleoncz
1

Je suppose que par "identique" vous faites référence au comportement.

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

1) Valeur renvoyée

2) Exceptions levées

3) Effets secondaires (c'est-à-dire changements dans le tas, le système de fichiers, etc.)

Dans ce cas, la première méthode propage toute exception, tandis que la seconde ne lève aucune exception vérifiée et avale également la plupart des exceptions non vérifiées, de sorte que le comportement est différent.

Cependant, si vous garantissez que "faire quelque chose" ne lève jamais d'exception, alors le comportement serait identique (bien que le compilateur exigera que l'appelant gère l'exception, dans la première version)

--Éditer--

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

Eyal Schneider
la source
1

Si vous avez levé une exception, la méthode enfant (qui remplace cela) 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
}
Sherif Eldeeb
la source
0

Vous souhaitez souvent que l'appelant gère l'exception. Supposons 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 au niveau de l'appelant. À moins que vous ne souhaitiez effectuer quelque chose dans l'une des méthodes lorsque cette méthode échoue.

Isaac
la source
0

L'appelant de cette méthode devra soit intercepter cette exception, soit la déclarer à nouveau 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 à se soucier 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);
    }
}
JSON C11
la source
0
private void calculateArea() throws Exception {
    ....do something
}

Cela lève l'exception, donc l'appelant est responsable de la gestion de cette exception, mais si l'appelant ne gère pas l'exception, il se peut qu'elle soit donnée à jvm, ce qui peut entraîner la fin anormale du programme.

Alors que dans le second cas:

private void calculateArea() {
    try {
        ....do something
    } catch (Exception e) {
        showException(e);
    }
}

Ici, l'exception est gérée par l'appelé, il n'y a donc aucun risque d'arrêt anormal du programme.

Try-catch est l'approche recommandée.

OMI,

  • Lance le mot-clé principalement utilisé avec les exceptions Checked pour convaincre le compilateur, mais il ne garantit pas l'arrêt normal du programme.

  • Le mot clé Throws délègue la responsabilité de la gestion des exceptions à
    l'appelant (JVM ou une autre méthode).

  • Le mot-clé Throws est requis pour les exceptions vérifiées uniquement, pour les exceptions non vérifiées, le mot-clé throws n'est pas utilisé.

Nitin Pawar
la source