Java permet de marquer les variables (champs / variables locales / paramètres) comme final
, pour empêcher leur ré-affectation. Je trouve cela très utile avec les champs, car cela m'aide à voir rapidement si certains attributs - ou une classe entière - sont censés être immuables.
D'autre part, je le trouve beaucoup moins utile avec les paramètres locaux et les paramètres, et j'évite en général de les marquer comme final
s'ils ne seraient jamais réaffectés (sauf exception évidente lorsqu'ils doivent être utilisés dans une classe interne). . Dernièrement, cependant, je suis tombé sur un code qui utilisait la version finale chaque fois que possible, ce qui, techniquement, fournit davantage d’informations.
N'ayant plus confiance en mon style de programmation, je me demande quels sont les autres avantages et inconvénients de l'application final
n'importe où, quel est le style le plus répandu dans l'industrie et pourquoi.
la source
final
ou non et optimisé en conséquence. Les compilateurs modernes sont assez intelligents pour le découvrir par eux-mêmes. Au moins sur les variables locales,final
est strictement à l'avantage des lecteurs humains. Si vos routines ne sont pas trop compliquées, la plupart des lecteurs humains devraient également être en mesure de les comprendre eux-mêmes.Réponses:
J'utilise
final
la même manière que toi. Pour moi, cela semble superflu pour les variables locales et les paramètres de méthode, et cela ne fournit aucune information supplémentaire utile.Une chose importante est que je m'efforce de garder mes méthodes courtes et propres , chacune effectuant une tâche unique. Ainsi, mes variables et paramètres locaux ont une portée très limitée et ne sont utilisés que dans un seul but. Cela minimise les chances de les réaffecter par inadvertance.
De plus, comme vous le savez sûrement,
final
ne garantit pas que vous ne pouvez pas changer la valeur / l’état d’une variable (non primitive). Seulement que vous ne pouvez pas réaffecter la référence à cet objet une fois initialisé. En d'autres termes, cela ne fonctionne de manière transparente qu'avec des variables de type primitif ou immuable. ConsidérerCela signifie que, dans de nombreux cas, cela ne permet toujours pas de comprendre plus facilement ce qui se passe dans le code, et une mauvaise compréhension peut en fait provoquer des bogues subtils difficiles à détecter.
la source
final
, merci :) mais bon point au sujet des méthodes courtes et propres - je suppose que si la méthode est suffisamment courte pour qu'il soit évident qu'une variable ne soit pas réaffectée, il y a encore moins de motif pour considérer lefinal
mot clé.Votre style de programmation Java et vos pensées vont bien - vous n'avez pas besoin de douter de vous-même.
C'est exactement pourquoi vous devriez utiliser le
final
mot clé. Vous déclarez que VOUS savez qu'il ne sera jamais réaffecté, mais personne d'autre ne le sait. L'utilisationfinal
désambiguise immédiatement votre code un tout petit peu plus.la source
final
indique l'intention, ce qui rend le code plus lisible. En outre, une fois que vous devez gérer le code du monde réel, vous remarquerez qu'il est rarement vierge et clair, et ajouter généreusementfinal
s partout où vous le pourrez vous aidera à détecter les bogues et à mieux comprendre le code hérité.final
l'intention des états, qui est généralement une bonne chose dans un morceau de code, mais cela revient à ajouter de l'encombrement visuel. Comme la plupart des choses en programmation, il y a un compromis à faire ici: est-ce que le fait d'exprimer le fait que votre variable ne sera utilisée qu'une seule fois vaut la peine de la verbosité ajoutée?final
. C'est peut-être la plupart des habitants, mais clairement pas tous . Pour moi, il n'y a pas "n'arrive jamais à changer". Il existe 2 types d'habitants bien distincts dans mon monde. Ceux qui ne sont jamais supposés changer (final) et ceux qui le doivent à la suite de ce que la tâche à accomplir dicte (très peu, ce qui rend les fonctions assez faciles à raisonner).Un des avantages de
final
/const
lorsque cela est possible est que cela réduit la charge mentale du lecteur de votre code.Il peut être assuré que la valeur / référence n’est jamais modifiée ultérieurement. Il n'a donc pas besoin de faire attention aux modifications pour comprendre le calcul.
J'ai changé d'avis à ce sujet après avoir appris les langages de programmation purement fonctionnels. Bon Dieu, quel soulagement, si vous pouvez faire confiance à une "variable" pour toujours conserver sa valeur initiale.
la source
final
ne garantit pas que vous ne pouvez pas changer la valeur / l’état d’une variable (non primitive). Seulement que vous ne pouvez pas réaffecter la référence à cet objet une fois initialisé.Je considère
final
dans les paramètres de méthode et les variables locales le code de bruit. Les déclarations de méthodes Java peuvent être assez longues (surtout avec les génériques) - il n'est pas nécessaire de les créer plus longtemps.Si les tests unitaires sont écrits correctement, l’attribution de paramètres «nocifs» sera prise en compte, il ne devrait donc jamais y avoir de problème. La clarté visuelle est plus importante que d'éviter un bug possible qui n'est pas détecté car la couverture de vos tests unitaires est insuffisante.
Des outils tels que FindBugs et CheckStyle peuvent être configurés pour interrompre la construction si une affectation est faite à des paramètres ou à des variables locales, si de telles choses vous tiennent à coeur.
Bien sûr, si vous devez les rendre finales, par exemple parce que vous utilisez la valeur dans une classe anonyme, alors pas de problème, c'est la solution la plus simple et la plus propre.
Outre l'effet évident d'ajouter des mots-clés supplémentaires à vos paramètres et de les camoufler ainsi à mon humble avis, l'ajout des paramètres de méthode finaux peut souvent rendre le code du corps de la méthode moins lisible, ce qui aggrave le code - d'être "bon", code doit être aussi lisible et aussi simple que possible. Pour un exemple artificiel, disons que j'ai une méthode qui doit fonctionner sans distinction de casse.
Sans
final
:Facile. Nettoyer. Tout le monde sait ce qui se passe.
Maintenant avec 'final', option 1:
Bien que définir les paramètres
final
empêche le codeur d’ajouter du code parce qu’il pense ne pas travailler avec la valeur originale, il existe un risque équivalent que le code plus bas puisse utiliser à lainput
placelowercaseInput
, ce qu’il ne devrait pas et contre lequel on ne peut pas se protéger, car vous pouvez " t le sortir de la portée (ou même assignernull
àinput
si cela pourrait même aider de toute façon).Avec 'final', option 2:
Nous venons tout juste de créer encore plus de bruit de code et d’avoir à invoquer
toLowerCase()
n fois.Avec 'final', option 3:
Parlez du bruit de code. Ceci est une épave de train. Nous avons une nouvelle méthode, un bloc d'exception requis, car un autre code peut ne pas l'appeler correctement. Plus de tests unitaires pour couvrir l'exception. Tout pour éviter une ligne simple, et à mon humble avis préférable et sans danger,.
Il y a également le problème que les méthodes ne devraient pas être si longues que vous ne pouvez pas facilement les assimiler visuellement et savoir en un coup d'œil qu'une affectation à un paramètre a eu lieu.
Je pense que c’est une bonne pratique / style que, si vous affectez un paramètre, vous le fassiez au début de la méthode, de préférence en première ligne ou juste après la vérification de base des entrées, en le remplaçant efficacement pour toute la méthode, ce qui a un effet cohérent au sein de la méthode. méthode. Les lecteurs savent qu’ils s’attendent à ce que toute tâche soit évidente (à proximité de la déclaration de signature) et dans un endroit cohérent, ce qui atténue considérablement le problème que l’ajout de final tente d’éviter. En fait, j'assigne rarement des paramètres, mais si je le fais, je le fais toujours au sommet d'une méthode.
Notez également que
final
ne vous protège pas réellement comme cela peut paraître au premier abord:final
ne vous protège pas complètement sauf si le type de paramètre est primitif ou immuable.la source
final
fournit la garantie partielle que vous traitez avec la mêmeDate
instance. Certaines garanties valent mieux que rien (si tant est que vous plaidiez pour des classes immuables à partir de rien!). Quoi qu'il en soit, dans la pratique, une grande partie de ce que vous dites devrait affecter les langues existantes immuables par défaut, mais ce n'est pas le cas, ce qui signifie que ce n'est pas un problème.final
, avec une possibilité de les rendre non définitifs pour les cas comme ci-dessus. Il est inutile de spammer la signature avec un mot clé.input
au lieu delowercaseInput
théorique. Bien que techniquement correct, il est facile de repérer une erreur une fois que cela vous cause un bogue, car vous pouvez clairement voir les différentes sémantiques des 2 variables nommées séparément à leur point d'utilisation (à condition de leur donner de bons noms). Pour moi, il est plus dangereux de confondre 2 utilisations sémantiquement différentes de valeurs séparées dans la même variable et donc le même nom. Cela peut rendre plus difficile le traçage des bogues, car vous devrez lire et comprendre tout le code précédent qui est en quelque sorte lié à la variable 1.Je laisse Eclipse mettre
final
avant chaque variable locale, car j’estime que cela facilitera la lecture du programme. Je ne le fais pas avec des paramètres, car je veux garder la liste de paramètres aussi courte que possible, idéalement, elle devrait tenir dans une ligne.la source
var
pour marquer les variables non finales. YMMV.var
! Malheureusement, ce n'est pas le cas en Java et il est maintenant trop tard pour changer de langue. Par conséquent, je suis prêt à supporter le désagrément mineur de l'écriturefinal
:)final
ajouté le mot clé, alors que seulement 10 à 20% auraient besoin d'unvar
...