En désignant une méthode de classe avec un modificateur
final
, nous entendons qu'aucune classe dérivée n'est capable de remplacer cette méthode en modifiant son implémentation interne. Autrement dit, nous parlons de la version finale de la méthode. La classe dans son ensemble peut également être marquée comme final
.
final class NoExtending {
// …
}
Une classe marquée comme final
ne peut pas être héritée et toutes ses méthodes acquièrent indirectement la propriété final
. L'utilisation de la fonctionnalité a final
dans les déclarations de classes et de méthodes peut augmenter le niveau de sécurité du code. Si une classe est équipée d'un modificateur final
, personne ne peut étendre la classe et probablement rompre son contrat par la même occasion. Si un signe final
désigne une méthode, vous pouvez pleinement vous fier à sa mise en œuvre interne dans toutes les situations sans crainte de « contrefaçon ». Il convient d'utiliser final
, par exemple, dans la déclaration d'une méthode qui nécessite la vérification du mot de passe saisi par l'utilisateur pour garantir l'exécution exacte de ce que la méthode voulait initialement. Un éventuel attaquant ne pourra pas modifier l'implémentation originale d'une telle méthode en « glissant » dans le programme une version remplacée de celle-ci, qui, par exemple, renvoie toujours la valeur true, indiquant la réussite de l'enregistrement de l'utilisateur, quel que soit le mot de passe. il est effectivement entré. Vous avez le droit, si la situation particulière le permet, d'aller plus loin et de déclarer final
la classe entière comme classe ; la méthode ValidatePassword
permettra d'acquérir indirectement la même propriété. L'utilisation d'un modificateur final
dans une déclaration de méthode ou de classe impose de sérieuses restrictions sur la possibilité d'une utilisation et d'un développement ultérieurs du code. L'utilisation d' final
une méthode dans une déclaration est un indicateur certain que l'implémentation de la méthode est autonome et complètement complète. Les autres programmeurs qui souhaitent utiliser votre classe, en élargissant ses fonctions pour répondre à leurs propres besoins, seront limités dans le choix des moyens pour atteindre leur objectif, voire complètement privés. En marquant final
une classe dans son ensemble, vous désactiverez sa capacité à être héritée et réduisez probablement considérablement son utilité pour les autres. Lorsque vous êtes sur le point d'utiliser le modificateur final
, assurez-vous que VOUS êtes prêt à de tels sacrifices et si cela en vaut la peine. Dans de nombreux cas, pour atteindre un niveau suffisant de sécurité du code, il n'est pas nécessaire de désigner la classe entière comme final
- il est tout à fait possible de préserver l'extensibilité de la classe en marquant final
uniquement ses éléments structurels « critiques » avec un modificateur. Dans ce cas, vous laisserez intactes les fonctions principales de la classe et en même temps autoriserez son héritage avec l'ajout de nouveaux membres, mais sans redéfinir les « anciens ». Bien entendu, les champs auxquels accède le code des méthodes final
doivent à leur tour être désignés comme final
soit private
, car sinon toute classe dérivée pourra modifier son contenu, affectant le comportement des méthodes correspondantes. Un autre effet de l'utilisation d'un modificateur final
est lié à la simplification du problème d'optimisation du code résolu par le compilateur. C'est ce qui arrive lorsqu'une méthode qui n'est pas marquée comme est appeléefinal
, le système d'exécution détermine la classe réelle de l'objet, associe l'appel au code le plus approprié du groupe de méthodes surchargées et transfère le contrôle à ce code. Mais si, par exemple, la méthode getName
de l'exemple de classe Attr
discuté précédemment avait été désignée comme final
, l'opération d'appel aurait pu être sensiblement simplifiée. Dans le cas le plus trivial, comme celui concernant getName
, le compilateur peut simplement remplacer l'appel de méthode par son corps de code. Ce mécanisme est appelé intégration de code (inlining). Lors de l'utilisation de la version en ligne de la méthode, getName
les deux expressions suivantes sont exécutées exactement de la même manière :
system.out.println("id = " + rose.name);
system.out.println("id = " + rose.getName());
Bien que les expressions ci-dessus soient équivalentes, la seconde a quand même un avantage, puisque la méthode getName
permet de donner au champ nom une propriété en lecture seule, et au code de classe d'avoir un certain degré d'abstraction, ce qui permet de modifier plus librement le implémentation de classe. Le même schéma d'optimisation peut être appliqué par le compilateur aux méthodes private
et statiс
, car elles ne permettent pas non plus de remplacement. L'utilisation d'un modificateur final
dans les déclarations de classe rend également certaines opérations de vérification de type plus efficaces. Dans ce cas, de nombreuses opérations de ce type peuvent être effectuées dès la phase de compilation et les erreurs potentielles sont donc détectées beaucoup plus tôt. Si le compilateur rencontre une référence à une classe dans le texte source final
, il peut être « sûr » que l'objet correspondant est du type spécifié. Le compilateur est capable de déterminer immédiatement la place occupée par une classe dans la hiérarchie globale des classes et de vérifier si elle est utilisée correctement ou non. Si le modificateur final
n'est pas appliqué, les contrôles correspondants sont effectués uniquement au stade de l'exécution du programme. Exercice 3.4. Est-il conseillé d'inclure le modificateur final dans les déclarations de méthode (et si oui, lesquelles) des classes véhicule et véhicule de tourisme ? Lien vers la source originale : http://src-code.net/metody-i-klassy-final-java
GO TO FULL VERSION