web-dev-qa-db-fra.com

Quel est le point de "classe finale" en Java?

Je lis un livre sur Java et il est dit que vous pouvez déclarer la classe entière comme final. Je ne peux pas penser à quoi que ce soit où je l'utiliserais. 

Je viens juste de commencer à programmer et je me demande si les programmeurs l’utilisent réellement pour leurs programmes . S'ils le font, quand l'utilisent-ils pour que je puisse mieux le comprendre et savoir quand l'utiliser? 

Si Java est orienté objet et que vous déclarez une classe final, cela n’arrête-t-il pas l’idée que la classe ait les caractéristiques des objets?

466
newbie

S'ils le font, quand l'utilisent-ils pour que je puisse mieux le comprendre et savoir quand l'utiliser?

Une classe final est simplement une classe qui ne peut pas être étendue.

(Cela ne signifie pas que toutes les références aux objets de la classe agiraient comme si elles étaient déclarées comme étant final.) 

Quand il est utile de déclarer une classe comme finale est couvert dans les réponses à cette question:

Si Java est orienté objet et que vous déclarez une classe final, cela n'empêche-t-il pas l'idée que la classe ait les caractéristiques des objets?

Dans un sens oui.

En marquant une classe comme finale, vous désactivez une fonctionnalité puissante et flexible du langage pour cette partie du code. Cependant, certaines classes ne devraient pas (et dans certains cas, peut pas) être conçues de manière à prendre en compte les sous-classes. Dans ces cas, il est logique de marquer la classe comme finale, même si cela limite la POO. (Rappelez-vous cependant qu'une classe finale peut toujours prolonger une autre classe non finale.)


Article associé: Java: Quand créer une classe finale

449
aioobe

En Java, les éléments avec le modificateur final ne peuvent pas être modifiés!

Cela inclut les classes finales, les variables finales et les méthodes finales:

  • Une dernière classe ne peut être étendue par aucune autre classe
  • Une variable finale ne peut pas être réaffectée à une autre valeur
  • Une dernière méthode ne peut pas être remplacée
167
andyqee

Un scénario où final est important, lorsque vous voulez empêcher l’héritage d’une classe, pour des raisons de sécurité. Cela vous permet de vous assurer que le code que vous utilisez ne peut pas être remplacé par par quelqu'un.

Un autre scénario concerne l'optimisation: il me semble que le compilateur Java intègre certains appels de fonctions issus des classes finales. Donc, si vous appelez a.x() et que a est déclaré final, nous savons au moment de la compilation quel sera le code et nous pourrons nous insérer dans la fonction appelante. Je ne sais pas si cela est réellement fait, mais au final, c'est une possibilité.

28
Shay Rojansky

Le meilleur exemple est 

public final class String

qui est une classe immuable et ne peut pas être étendu ..__ Bien sûr, il ne suffit pas de rendre la classe finale immuable.

19
javadeveloper

Si vous imaginez la hiérarchie des classes comme un arbre (comme en Java), les classes abstraites ne peuvent être que des branches et les classes finales sont celles qui ne peuvent être que des feuilles. Les classes qui ne font partie d'aucune de ces catégories peuvent être à la fois des branches et des feuilles.

Il n’ya pas violation des principes de OO ici, final fournit simplement une symétrie de Nice.

En pratique, vous voulez utiliser final si vous voulez que vos objets soient immuables ou si vous écrivez une API, pour signaler aux utilisateurs de l'API que la classe n'est tout simplement pas destinée à une extension.

15
biziclop

Lecture pertinente: Le principe d'ouverture-fermeture de Bob Martin.

Citation clé:

Les entités logicielles (classes, modules, Fonctions, etc.) doivent être ouvertes pour Extension, mais fermée pour Modification.

Le mot clé final permet de l'appliquer en Java, qu'il soit utilisé sur des méthodes ou des classes.

15

Le mot clé final signifie lui-même que quelque chose est final et qu'il n'est pas censé être modifié de quelque manière que ce soit. Si une classe est marquée final, elle ne peut être ni étendue ni sous-classée. Mais la question est: pourquoi marquons-nous une classe final? OMI il y a plusieurs raisons:

  1. Normalisation: Certaines classes exécutent des fonctions standard et ne sont pas destinées à être modifiées, par exemple. des classes remplissant diverses fonctions liées aux manipulations de chaînes ou à des fonctions mathématiques, etc.
  2. Raisons de sécurité: nous écrivons parfois des classes qui exécutent diverses fonctions liées à l’authentification et aux mots de passe et nous ne voulons pas qu’elles soient modifiées par quelqu'un d’autre. 

J'ai entendu dire que la classe de notation final améliore l'efficacité, mais franchement, je ne pouvais pas trouver que cet argument avait beaucoup de poids.

Si Java est orienté objet et que vous déclarez une classe finale, n’est-ce pas arrêter l'idée de classe ayant les caractéristiques des objets?

Peut-être que oui, mais parfois c'est le but recherché. Parfois, nous faisons cela pour obtenir des avantages plus importants en matière de sécurité, etc. en sacrifiant la capacité de cette classe à être étendue. Mais une dernière classe peut toujours prolonger une classe si nécessaire.

Par ailleurs, nous devrions préférer la composition à l'héritage et le mot clé final aide réellement à appliquer ce principe.

9
i_am_zero

POUR ADRESSER LE PROBLÈME DE CLASSE FINAL:

Il y a deux façons de faire une classe finale. La première consiste à utiliser le mot-clé final dans la déclaration de classe:

public final class SomeClass {
  //  . . . Class contents
}

La deuxième façon de rendre une classe finale est de déclarer tous ses constructeurs comme privés:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

Le marquer comme final vous évite d'avoir à vérifier qu'il s'agit bien d'une finale, ce qui prouve que vous regardez bien cette classe de tests. regarde le public à première vue.

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

Malheureusement, le seul constructeur de la classe étant privé, il est impossible d'étendre cette classe. Dans le cas de la classe Test, il n'y a aucune raison pour que la classe soit finale. La classe Test est un bon exemple de la façon dont les classes finales implicites peuvent causer des problèmes.

Vous devez donc le marquer comme final lorsque vous rendez implicitement une classe finale en rendant son constructeur privé.

5
mel3kings

final class peut éviter de casser l'API publique lorsque vous ajoutez de nouvelles méthodes

Supposons que sur la version 1 de votre classe Base, vous effectuez les opérations suivantes:

public class Base {}

et un client fait:

class Derived extends Base {
    public int method() { return 1; }
}

Ensuite, si dans la version 2, vous souhaitez ajouter une méthode method à Base:

class Base {
    public String method() { return null; }
}

cela briserait le code client.

Si nous avions utilisé final class Base à la place, le client n'aurait pas été en mesure d'hériter et l'ajout de méthode n'aurait pas cassé l'API.

Soyez prudent lorsque vous faites un cours "final". Parce que si vous voulez écrire un test unitaire pour une classe finale, vous ne pouvez pas sous-classer cette classe finale afin d'utiliser la technique de rupture de dépendance "Méthode Subclass and Override" décrite dans le livre de Michael C. Feathers "Travailler efficacement avec du code hérité" . Dans ce livre, Feathers a déclaré: "Sérieusement, il est facile de croire que scellé et définitif sont une erreur erronée, qu'ils n'auraient jamais dû être ajoutés aux langages de programmation. Mais le véritable défaut incombe à nous. Lorsque nous dépendons directement de bibliothèques qui sont hors de notre contrôle, nous demandons simplement des ennuis. "

5
Ben Wu

Si la classe est marquée final, cela signifie que la structure de la classe ne peut être modifiée par aucun élément externe. Là où c'est le plus visible, c'est quand vous faites un héritage polymorphe traditionnel, fondamentalement class B extends A ne fonctionnera tout simplement pas. C'est fondamentalement un moyen de protéger certaines parties de votre code (dans la mesure de) .

Pour clarifier, le marquage de la classe final ne marque pas ses champs comme étant final et en tant que tel ne protège pas les propriétés de l'objet mais la structure de classe réelle.

5
Esko

En Java, le mot clé final est utilisé pour les occasions ci-dessous.

  1. Variables finales
  2. Méthodes finales
  3. Classes finales

En Java, les variables finales ne peuvent pas être réaffectées, les classes finales ne peuvent pas être étendues et les méthodes finales ne peuvent pas remplacer.

3

Un avantage de garder une classe en finale: -

La classe String est maintenue finale afin que personne ne puisse remplacer ses méthodes et modifier les fonctionnalités. Par exemple, personne ne peut changer les fonctionnalités de la méthode length (). Il retournera toujours la longueur d'une chaîne.

Les développeurs de cette classe ne voulaient personne pour changer les fonctionnalités de cette classe, il l'a donc gardée comme finale.

3
Rahul

Oui, parfois, vous voudrez peut-être cela, pour des raisons de sécurité ou de rapidité. C'est aussi fait en C++. Ce n'est peut-être pas cela applicable aux programmes, mais davantage aux frameworks . http://www.glenmccl.com/perfj_025.htm

3
James

Une dernière classe est une classe qui ne peut pas être étendue. Les méthodes peuvent également être déclarées comme finales pour indiquer que les sous-classes ne peuvent pas être remplacées. 

Empêcher le sous-classement de la classe peut s'avérer particulièrement utile si vous écrivez des API ou des bibliothèques et souhaitez éviter d'être étendu pour modifier le comportement de base.

3
JuanZe

La classe Android Looper en est un bon exemple pratique. http://developer.Android.com/reference/Android/os/Looper.html

La classe Looper fournit certaines fonctionnalités qui ne doivent PAS être remplacées par une autre classe. Par conséquent, pas de sous-classe ici.

1
jaamit

pensez à FINAL comme à la "fin de la ligne" - ce type ne peut plus produire de progéniture. Ainsi, lorsque vous le voyez de cette manière, vous rencontrerez une tonne de scénarios du monde réel qui vous obligent à marquer un marqueur de «fin de ligne» à la classe. C'est une conception dirigée par le domaine - si votre domaine exige qu'une ENTITY (classe) donnée ne puisse pas créer de sous-classes, marquez-le comme FINAL.

Je dois noter que rien ne vous empêche d’hériter d’une classe "devrait être étiquetée comme finale". Mais cela est généralement classé dans la catégorie "abus d'héritage" et il est effectué car le plus souvent, vous souhaitez hériter d'une fonction de la classe de base de votre classe.

La meilleure approche consiste à examiner le domaine et à le laisser dicter vos décisions de conception.

1
Kingz

Comme indiqué ci-dessus, si vous souhaitez que personne ne puisse modifier les fonctionnalités de la méthode, vous pouvez la déclarer comme finale.

Exemple: chemin du fichier du serveur d'application pour le téléchargement/téléchargement, division de la chaîne en fonction de l'offset. Vous pouvez ainsi déclarer cette méthode Final afin que ces méthodes ne soient pas modifiées. Et si vous voulez de telles méthodes finales dans une classe séparée, définissez cette classe comme classe finale. Ainsi, la classe finale aura toutes les méthodes finales, alors que la méthode finale peut être déclarée et définie dans une classe non finale.

1
lok

Disons que vous avez une classe Employee qui a une méthode greet. Lorsque la méthode greet est appelée, elle affiche simplement Hello everyone!. Il s’agit donc de la méthodecomportement attendude greet

public class Employee {

    void greet() {
        System.out.println("Hello everyone!");
    }
}

Maintenant, laissez GrumpyEmployee sous-classe Employee et substituez la méthode greet comme indiqué ci-dessous. 

public class GrumpyEmployee extends Employee {

    @Override
    void greet() {
        System.out.println("Get lost!");
    }
}

Maintenant, dans le code ci-dessous, jetez un coup d’œil à la méthode sayHello. Il prend comme paramètre Employee et appelle la méthode saluer en espérant pouvoir dire Hello everyone!. Nous obtenons toutefois Get lost!. Ce changement de comportement est dû à Employee grumpyEmployee = new GrumpyEmployee();

public class TestFinal {
    static Employee grumpyEmployee = new GrumpyEmployee();

    public static void main(String[] args) {
        TestFinal testFinal = new TestFinal();
        testFinal.sayHello(grumpyEmployee);
    }

    private void sayHello(Employee employee) {
        employee.greet(); //Here you would expect a warm greeting, but what you get is "Get lost!"
    }
}

Cette situation peut êtreévitéesi la classe Employee a été créée final. Imaginez la quantité de chaos qu'un programmeur effronté pourrait causer si String Class n'était pas déclaré comme final

1
Andy

Les classes finales ne peuvent pas être prolongées. Donc si vous voulez qu'une classe se comporte d'une certaine manière et que personne ne redéfinisse les méthodes (avec peut-être un code moins efficace et plus malveillant), vous pouvez déclarer la classe entière comme méthode finale ou spécifique modifié. 

Étant donné que la déclaration d'une classe n'empêche pas l'instanciation d'une classe, cela ne signifie pas que cela empêchera la classe d'avoir les caractéristiques d'un objet. C'est juste que vous devrez vous en tenir aux méthodes telles qu'elles sont déclarées dans la classe. 

1
skhaapioloir

La classe finale ne peut pas être étendue davantage. Si nous n'avons pas besoin de rendre une classe héritable en Java, nous pouvons utiliser cette approche.

Si nous devons simplement créer des méthodes particulières dans une classe pour ne pas les remplacer, nous pouvons simplement leur placer le mot-clé final. Là, la classe est toujours héritable.

0
G. Kith

En bref, une classe, une variable ou une méthode déclarée comme finale ne peut pas être modifiée. 

Ce qui est plus important est mon avis:

Honnêtement, j'estime qu'un mot clé final est une erreur, car son existence permet à un utilisateur de définir quelque chose qui est pasfinal. Tout en Java doit être final par défaut à l'exception des méthodes d'interface (par sa définition). C'était un choix malchanceux de laisser toutes les méthodes d'instance être virtual par défaut (en termes de c # ). La clé est de forcer l'utilisateur à penser d'abord et à définir explicitement de manière honteuse une méthode comme étant virtual. Cela l'inciterait à se demander si cette méthode devrait laisser les autres le remplacer, si elle est really un besoin ou le persuader de redéfinir son code.

0
Nikolas