Java: Signification de catch (Final SomeException e)?

Que fait final dans l'expression Java suivante?

catch (final SomeExceptionType e)
25
demandé sur Matteo 2010-08-19 01:22:07

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.

26
répondu Edwin Buck 2010-08-18 22:20:58

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.)

10
répondu Tom Hawtin - tackline 2012-07-30 13:34:26

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.

2
répondu Thorbjørn Ravn Andersen 2010-08-18 23:01:50

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 :

  1. 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.)
  2. 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.

2
répondu Austin D 2017-05-23 12:02:17