web-dev-qa-db-fra.com

Utilisation excessive du mot clé "final" dans Java

Bien que je comprenne à quoi sert le mot clé final dans le contexte des classes et des méthodes ainsi que l'intention de son utilisation en ce qui concerne les variables; cependant, le projet sur lequel je viens de commencer à travailler semble en avoir un nombre excessif et je suis curieux de savoir la logique derrière.

L'extrait de code suivant n'est qu'un court exemple, car je ne vois pas grand-chose dans le mot clé final pour les variables key et value:

private <K, V> Collection<V> getValuesForKeys(
    final Map<K, V> map, final Collection<K> keys) 
{
    final Collection<V> values = new ArrayList<V>(keys.size());
    for (final K key : keys) {
        final V value = map.get(key);
        if (value != null) {
            values.add(value);
        }
    }
    return values;
}

J'ai fait un peu de lecture de l'utilisation à travers des articles que j'ai trouvés via Google; cependant, le modèle fait-il vraiment des choses comme aider le compilateur à optimiser le code?

118
rjzii

Il existe de nombreuses références suggérant un libéraltilisation definal . Le Java Language Specification a même ne section sur les variables finales . Diverses règles dans les outils d'analyse statique le supportent également - PMD a même un nombre de règles pour détecter quand final peut être utilisé . Les pages que j'ai liées pour fournir un certain nombre de points sur ce que fait final et pourquoi vous devez l'utiliser librement.

Pour moi, l'utilisation libérale de final a accompli deux choses dans la plupart du code, et ce sont probablement les choses qui ont poussé l'auteur de votre exemple de code à l'utiliser:

  1. Cela rend l'intention du code beaucoup plus claire et conduit à un code auto-documenté. L'utilisation de final empêche la valeur d'un objet primitif de changer ou de créer un nouvel objet et d'écraser un objet existant. S'il n'est pas nécessaire de modifier la valeur d'une variable et que quelqu'un le fait, le IDE et/ou compilateur fournira un avertissement. Le développeur doit soit résoudre le problème, soit supprimer explicitement le final modificateur à partir de la variable. Dans les deux cas, une réflexion est nécessaire pour garantir que le résultat escompté est atteint.

  2. Selon votre code, il sert d'indicateur au compilateur pour activer potentiellement les optimisations. Cela n'a rien à voir avec le temps de compilation, mais ce que le compilateur peut faire pendant la compilation. Il n'est pas non plus garanti de faire quoi que ce soit. Cependant, signaler au compilateur que la valeur de cette variable ou de l'objet auquel elle fait référence ne changera jamais pourrait potentiellement permettre des optimisations de performances.

Il existe également d'autres avantages liés à la concurrence. Lorsqu'il est appliqué au niveau d'une classe ou d'une méthode, il s'agit de garantir ce qui peut être remplacé ou hérité. Cependant, cela dépasse la portée de votre exemple de code. Encore une fois, les articles que j'ai liés pour approfondir la façon dont vous pouvez appliquer final.

La seule façon de savoir pourquoi l'auteur du code a décidé d'utiliser final est de trouver l'auteur et de demander par vous-même.

127
Thomas Owens

Les principaux avantages de "final" dans mon esprit sont doubles:

  • Les variables finales sont "plus sûres" que les variables non finales, car une fois qu'elles sont liées, il n'y a jamais de question sur leur état actuel.
  • En raison de ce qui précède, faire une variable finale soulage le programmeur de la jonglerie mentale excessive - il/elle n'a pas à parcourir le code pour voir si la variable a changé. Cet heureux état de choses sera familier à toute personne ayant passé du temps dans un environnement de langage fonctionnel.

Quant à cet exemple spécifique, il se peut que le programmeur ait pris l'habitude "finale" et applique simplement le mot-clé "final" partout comme une évidence. (Je suis sceptique quant à la notion selon laquelle le mot clé final aiderait le compilateur lorsqu'il parle d'affectations individuelles - il n'a sûrement pas besoin d'aide pour déterminer qu'une seule affectation a eu lieu?)

Je suis d'avis que Java l'a récupéré - il ne devrait pas y avoir de mot clé "final" pour les variables, tout devrait être "final" par défaut, et si vous voulez une variable mutable, vous devriez devez ajouter un mot clé pour cela ("var" ou un autre). (Comme un autre commentateur l'a mentionné, scala a deux mots clés - "val" et "var" pour les variables finales et non finales) , respectivement - je vais le prendre).

37
nerdytenor

En Java le seul endroit à ma connaissance où le mot clé final est requis est de faire un variable disponible de manière fiable pour une classe anonyme (puisque le compilateur fait une ruse sous les couvertures nécessitant que cette valeur ne puisse pas changer).

C'est - à ma connaissance - un mythe que le mot-clé final permet au compilateur Java d'optimiser le code, comme toutes les optimisations qui comptent se produit dans la partie JIT du runtime.

C'est donc une question de goût. Il y a cependant un avantage très significatif à utiliser beaucoup de finales, à savoir rendre le code plus facile à lire pour les futurs responsables.

Le marquage d'une variable comme final indique au lecteur que cette variable ne change jamais, jamais lorsqu'elle est affectée. Ceci est très important lors de la lecture du code car vous savez quand vous avez besoin de connaître la valeur de la variable que c'est la même que dans l'affectation initiale et que vous n'avez pas à analyser mentalement tout le code entre les deux pour voir si la variable est à nouveau affectée avec autre chose.

De plus, si vous voyez qu'une variable n'est pas non marquée avec final vous savez que elle sera encore changé ! Il s'agit d'une information extrêmement importante qui peut être transmise au lecteur simplement en ayant cinq caractères manquants.

Tout ce qui peut aider le responsable à faire son travail plus rapidement et de manière plus fiable signifie que l'application est moins chère à maintenir! En d'autres termes, final permet d'économiser de l'argent réel.

Remarque: Eclipse a une option de "nettoyage des sources" qui peut insérer des finales si possible. Cela peut être utile à la fois pour écrire du nouveau code et pour conserver l'ancien (insérer les finales, si certains manquent, la variable est modifiée après l'affectation initiale). Mon intuition est que c'est ce que l'auteur original a découvert et décidé d'utiliser.

Le sujet est traité plus en détail sur https://stackoverflow.com/q/316352/53897

13
user1249

Je pense que la réponse à cette question est plus simple que d'autres suggèrent. Ce n'est pas une question d'intention ou de design. Il y a longtemps, il était vrai que l'ajout de final à certains endroits (en particulier pour les méthodes et les classes) permettait à la JVM d'optimiser de manière plus agressive. En conséquence, certaines personnes sont devenues folles et ont mis la finale littéralement partout pour essayer d'obtenir leur code pour aller plus vite.

Je dois ajouter que ce n'est pas le compilateur, mais la JVM qui fait l'optimisation. De plus, je doute que le fait de mettre une finale sur une variable locale n'ait jamais fait de différence dans les performances.

Enfin, l'utilisation de final ne ferait probablement pas beaucoup de différence ces jours-ci, car les optimisations JVM ont quelque peu avancé.

8
redjamjar

Il me semble que le mot clé final est utilisé dans ce contexte pour créer une collection immuable. Les collections immuables sont plus simples à raisonner et plus sûres à utiliser dans les programmes nécessitant une concurrence (plusieurs threads ).

Ce n'est pas vrai, bien sûr. Le mot clé final garantit uniquement que la référence à la collection ne peut pas être remplacée par une référence à une autre collection ou null.

1
Robert Harvey