Java: Signification de catch (Final SomeException e)?
Que fait final
dans l'expression Java suivante?
catch (final SomeExceptionType e)
4 réponses
ça veut dire:
Catch " SomeExceptionType "dans la variable" e "avec la promesse que nous n'assignerons pas une exception différente à" e " pendant le traitement de l'exception.
la plupart du temps, c'est exagéré, comme si j'attrapais une exception dans un nom de variable temporaire (e seulement est valide pour le bloc de traitement de l'exception), Je n'ai pas à me contrôler si strictement que de ne pas me faire confiance pour attribuer une exception différente (éventuellement créée) pour le même nom de variable.
cela dit, peut-être que ce bloc est fortement maintenu par une équipe d'individus différents d'esprit, et on voulait juste être très sûr que e était l'exception capturée à l'origine.
---- Edité en réponse au commentaire ----
Je ne vois pas d'excellente raison pour faire ça. Puisque " e "n'est pas un membre (statique ou autre) le nom" e " ne sera pas utilisé par le fichier de classe post-compilation. Une autre façon d'indiquer ceci est que lorsque vous entrez le bloc de traitement d'exception du bytecode JVM, l'objet ne sera pas assigné à l'un des noms de membres accessibles par le cadre de traitement JVM, il sera poussé vers la pile de traitement interne du cadre courant du Thread.
même si deux threads avaient accès au même objet, chaque thread aurait son propre cadre, de sorte que le compilateur a retiré le nom" e " de la pile interne d'un cadre ne pouvait pas être modifié par l'autre thread.
avec cela à l'esprit, le seul avantage de déclarer" e "final est de s'assurer que les codeurs futurs ne mettent pas accidentellement" e " après être entré dans le bloc. Peut-être voulaient-ils rendre le code plus robuste dans un environnement multi-threadé, mais les variables temporaires (celles avec des noms qui ne sont valides que dans le bloc) n'ont pas de noms post-compilation, ils sont poussés sur la pile du cadre.
C'est pourquoi
public int safe() {
int x = 5;
x = x + 5;
return x;
}
est généralement considéré comme sûr, parce qu'il le fait (en pseudo bytecode)
(In the thread's current frame)
push 5
push 5
add integers
return
Alors que ce n'est pas thread-safe
int x = 5;
public void unsafe() {
x = 5;
x = x + 5;
return x;
}
parce qu'il fait ceci
(in the thread's current frame)
push "this"
push 5
set member x
push "this"
get member x
push 5
add integer
set member x
get member x
return
ce dernier bytecode fait apparaître que l'entrelacement de deux threads crée des communications thread-to-thread en utilisant le membre x et un intermédiaire, alors que le premier bloc de code ne peut pas avoir de communication inter-thread parce qu'il n'y a pas intermédiaire.
actuellement cela signifie final
à peu près la même chose que n'importe quelle variable locale, sauf qu'elle est toujours "définitivement assignée".
Au cours des dernières JDK7 construit, un Projet de Pièce de monnaie de changement de la langue permet d'indiquer un degré d'implicite typage statique est en cours. Un seul catch
peut attraper un certain nombre de différentes exceptions vérifiées par un type de base commun, et rethrow avec le contexte d'enclos ayant seulement attraper ou déclarer ces exceptions que pourrait (statiquement parlant) être jeté dans le try
. (Voir le lien pour une meilleure explication.)
le mot-clé final
sur les variables signifie que la variable ne peut être assignée qu'une seule fois, et comme l'assignation ici est faite par le compilateur cela signifie que la variable ne peut pas être changée plus tard dans le code.
il s'agit d'une propriété importante car elle signifie pour le responsable que cette variable particulière aura cette valeur particulière partout où elle est utilisée et il n'est pas nécessaire de tenir compte de l'endroit où elle change. Cela est reconnu comme étant si utile que L'action" Clean up "dans Eclipse permet d'ajouter" final "partout où cela est possible, et je crois que ce que vous voyez est le" résultat d'un tel nettoyage automatique, parce que la plupart des programmeurs humains garderaient le catch-block court de sorte qu'une telle indication n'est pas nécessaire.
la question, "Que fait finally
?"est abordé dans d'autres réponses à cette question, et ici , ici , et ici . Mais dans le contexte d'un try-catch bloc, le Java Language Specification (JLS) §4.12.4 stipule (emphasis my own):
- Une ressource try-with-resources la déclaration (§14.20.3) et un paramètre d'exception d'une clause de prises multiples (§14.20) sont implicitement déclarée finale .
- un paramètre d'exception d'une clause de prise unique (§14.20) peut être effectivement final au lieu d'être explicitement déclaré final. Un tel paramètre est jamais implicitement déclaré final .
Dans un multi-clause catch :
L'ajout du mot-clé final
à une multi-catch clause rend tout simplement explicite le fait que le variable
est implicitement final. En général, chaque fois que le mot-clé final
transmet des informations supplémentaires qui aident à rendre votre code plus lisible/maintenable, utilisez-le.
Dans un uni-clause catch
, d'autre part, le paramètre d'exception dans un uni-clause catch est jamais implicitement final. Ainsi, l'utilisation du mot-clé final
à une uni-catch clause empêche quelque chose comme ce qui suit d'arriver:
try {
throw new Exception();
catch (Exception e){
e = null;
e.printStackTrace(); //throws a NullPointerException
}
La question est évidente dans cet exemple simple. Mais deux cas peuvent être moins évidents et justifier l'utilisation de finally
:
- si le bloc de capture est plus compliqué, une réaffectation accidentelle est possible. (Bien que, si le bloc catch est compliqué, vous le faites probablement mal.)
- pour prévenir les problèmes causés pendant la maintenance du code. L'ajout de
final
à la variable d'exception permettra de s'assurer que la réaffectation est prise en compte lors de la compilation, plutôt que lors de l'exécution
en règle générale, utilisez le mot-clé final
dans un uni-catch clause de la même manière que vous utiliseriez le final
mot-clé pour un paramètre de méthode :
JLS§4.12.4 : déclarer une variable finale peut servir de documentation utile que sa valeur ne changera pas et peut aider à éviter des erreurs de programmation.