web-dev-qa-db-fra.com

Pourquoi le compilateur autorise-t-il des lancements alors que la méthode ne lèvera jamais l'exception

Je me demande pourquoi le Java autorise les lancers dans la déclaration de méthode alors que la méthode ne lèvera jamais l'exception. Parce que "throws" est un moyen de gérer l'exception (en disant à l'appelant de la gérer) .

Puisqu'il y a deux façons de gérer les exceptions (lancers et try/catch). Dans un try/catch, il n'autorise pas le catch d'une exception non levée dans le bloc try mais il permet un throws dans une méthode qui ne peut pas lever l'exception.

private static void methodA() {
    try {
        // Do something
        // No IO operation here
    } catch (IOException ex) {  //This line does not compile because
                              //exception is never thrown from try
        // Handle   
    }
}

private static void methodB() throws IOException { //Why does this //compile when excetion is never thrown in function body
    //Do Something 
    //No IO operation
}
18
PsyAp

La clause throws fait partie du contrat de la méthode. Cela nécessite que l'appelant de la méthode se comporte comme si l'exception spécifiée pouvait être levée par la méthode (c'est-à-dire soit intercepter l'exception soit déclarer sa propre clause throws).

Il est possible que la version initiale d'une méthode ne lève pas l'exception spécifiée dans la clause throws, mais une future version peut la lancer sans casser l'API (c'est-à-dire que tout code existant qui appelle la méthode passera toujours la compilation) .

Le contraire c'est aussi possible. Si la méthode utilisée pour lever l'exception spécifiée dans la clause throws, mais qu'une future version de celle-ci ne la lance plus, vous devez conserver la clause throws afin de ne pas casser le code existant qui utilise votre méthode.

Premier exemple:

Supposons que vous ayez ce code qui utilise methodB:

private static void methodA() {
    methodB(); // doesn't have throws IOException clause yet
}

Si plus tard vous voulez changer methodB pour lancer IOException, methodA arrêtera de passer la compilation.

Deuxième exemple:

Supposons que vous ayez ce code qui utilise methodB:

private static void methodA() {
    try {
        methodB(); // throws IOException
    }
    catch (IOException ex) {

    }
}

Si vous supprimez la clause throws d'une future version de methodB, methodA ne passera plus la compilation.

Cet exemple n'est pas très intéressant lorsque methodA est private, car il ne peut être utilisé que localement (dans la même classe, où il est facile de modifier toutes les méthodes qui l'appellent).

Cependant, si elle devient public, vous ne savez pas qui utilise (ou utilisera) votre méthode, vous n'avez donc aucun contrôle sur tout le code qui peut se casser à la suite de l'ajout ou de la suppression du throws clause.

Et s'il s'agit d'une méthode d'instance, il y a une autre raison pour autoriser la clause throws même si vous ne lancez pas l'exception - la méthode peut être substituée et la méthode prioritaire peut lever l'exception même si l'implémentation de la classe de base ne fait pas.

26
Eran

Parce que la signature définit le contrat de la méthode. Même si la méthode ne lance pas d'exception IO maintenant, peut-être le sera-t-elle à l'avenir, et vous voulez vous préparer à cette possibilité.

Supposons que vous fournissiez simplement une implémentation factice pour la méthode pour l'instant, mais vous savez que, plus tard, l'implémentation réelle lèvera potentiellement une IOException. Si le compilateur vous empêchait d'ajouter cette clause throws, vous seriez obligé de retravailler tous les appels (récursivement) à cette méthode une fois que vous auriez fourni l'implémentation réelle de la méthode.

8
JB Nizet

Le lancement de mots clés indique au programmeur qu'il pourrait y avoir une exception IOException dans la méthode. Maintenant, si vous n'avez pas spécifié try/catch, cela signifie que lorsque l'exception est levée, le programme cessera de fonctionner, tandis que dans try/catch, vous le gérerez en faisant autre chose si l'exception levée.

Utilisez les lancers pour plus de lisibilité et spécifiez la possibilité d'exception et utilisez try/catch pour dire au programme quoi faire en cas d'exception.

0
IvanM