L'utilisation du mot-clé final en Java améliore-t-elle les performances?

347

En Java, nous voyons beaucoup d'endroits où le finalmot - clé peut être utilisé mais son utilisation est rare.

Par exemple:

String str = "abc";
System.out.println(str);

Dans le cas ci-dessus, cela strpeut être le cas, finalmais cela est généralement omis.

Lorsqu'une méthode ne sera jamais remplacée, nous pouvons utiliser le mot-clé final. De même dans le cas d'une classe qui ne va pas être héritée.

L'utilisation du mot-clé final dans l'un ou l'ensemble de ces cas améliore-t-elle vraiment les performances? Si oui, alors comment? S'il vous plaît, expliquez. Si la bonne utilisation de finalimporte vraiment pour les performances, quelles habitudes un programmeur Java doit-il développer pour utiliser au mieux le mot-clé?

Abhishek Jain
la source
Je ne pense pas, mon ami, la répartition des méthodes (mise en cache du site d'appel et ...) est un problème dans les langages dynamiques et non dans les langages de type statique
Jahan
Si j'exécute mon outil PMD (plugin pour Eclipse) utilisé à des fins de révision, il suggère de faire des changements pour les variables au cas où indiqué ci-dessus. Mais je n'ai pas compris son concept. Vraiment la performance frappe tellement ??
Abhishek Jain
5
Je pensais que c'était une question d'examen typique. Je me souviens que finale n'avoir une influence sur la performance, IIRC classes finales peuvent être optimisés par le JRE d' une certaine façon parce qu'ils ne peuvent pas être sous - classé.
Kawu
J'ai fait tester ça. Sur toutes les machines virtuelles Java, j'ai testé l'utilisation de final sur les variables locales a amélioré les performances (légèrement, mais peut néanmoins être un facteur dans les méthodes utilitaires). Le code source est dans ma réponse ci-dessous.
rustyx
1
"L'optimisation prématurée est la racine de tout Mal". Laissez simplement le compilateur faire son travail. Écrivez du code lisible et bien commenté. C'est toujours le meilleur choix!
kaiser

Réponses:

285

Habituellement non. Pour des méthodes virtuelles, HotSpot garde la trace de savoir si la méthode a effectivement été surchargée, et est en mesure d'effectuer des optimisations telles que inline sur l' hypothèse qu'une méthode n'a pas été remplacé - jusqu'à ce qu'il charge une classe qui remplace la méthode, à quel point il peut annuler (ou annuler partiellement) ces optimisations.

(Bien sûr, cela suppose que vous utilisez HotSpot - mais c'est de loin la JVM la plus courante, donc ...)

À mon avis, vous devez utiliser finalune conception et une lisibilité claires plutôt que pour des raisons de performances. Si vous souhaitez modifier quoi que ce soit pour des raisons de performances, vous devez effectuer les mesures appropriées avant de déformer le code le plus clair - de cette façon, vous pouvez décider si les performances supplémentaires obtenues valent la moins bonne lisibilité / conception. (D'après mon expérience, cela ne vaut presque jamais la peine; YMMV.)

EDIT: Comme les champs finaux ont été mentionnés, il vaut la peine de mentionner qu'ils sont de toute façon souvent une bonne idée, en termes de conception claire. Ils modifient également le comportement garanti en termes de visibilité entre les threads: une fois qu'un constructeur a terminé, tous les champs finaux sont garantis visibles immédiatement dans d'autres threads. C'est probablement l'utilisation la plus courante de finalmon expérience, bien qu'en tant que partisan de la règle de base de Josh Bloch "concevoir pour l'héritage ou l'interdire", je devrais probablement l'utiliser finalplus souvent pour les cours ...

Jon Skeet
la source
1
@Abhishek: A propos de quoi en particulier? Le point le plus important est le dernier - que vous ne devriez certainement pas vous inquiéter à ce sujet.
Jon Skeet
9
@Abishek: finalest généralement recommandé car il rend le code plus facile à comprendre et aide à trouver les bogues (car il rend l'intention des programmeurs explicite). PMD recommande probablement d'utiliser en finalraison de ces problèmes de style, et non pour des raisons de performances.
sleske
3
@Abhishek: Beaucoup d'entre elles sont susceptibles d'être spécifiques à la JVM et peuvent s'appuyer sur des aspects très subtils du contexte. Par exemple, je crois que la JVM du serveur HotSpot permettra toujours l'inclusion de méthodes virtuelles en cas de substitution dans une classe, avec une vérification de type rapide le cas échéant. Mais les détails sont difficiles à cerner et pourraient bien changer entre les versions.
Jon Skeet
5
Ici , je citerais Effective Java, 2e édition, article 15, Réduire mutabilité Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.. En outre An immutable object can be in exactly one state, the state in which it was created.vs Mutable objects, on the other hand, can have arbitrarily complex state spaces.. D'après mon expérience personnelle, l'utilisation du mot-clé finaldevrait mettre en évidence l'intention du développeur de tendre vers l'immuabilité, et non "d'optimiser" le code. Je vous encourage à lire ce chapitre, fascinant!
Louis F.
2
D'autres réponses montrent que l'utilisation du finalmot - clé sur les variables pourrait réduire la quantité de bytecode, ce qui pourrait produire un effet sur les performances.
Julien Kronegg
86

Réponse courte: ne vous en faites pas!

Longue réponse:

Lorsque vous parlez de variables locales finales, gardez à l'esprit que l'utilisation du mot-clé finalaidera le compilateur à optimiser statiquement le code , ce qui peut finalement aboutir à un code plus rapide. Par exemple, les chaînes finales a + bde l'exemple ci-dessous sont concaténées statiquement (au moment de la compilation).

public class FinalTest {

    public static final int N_ITERATIONS = 1000000;

    public static String testFinal() {
        final String a = "a";
        final String b = "b";
        return a + b;
    }

    public static String testNonFinal() {
        String a = "a";
        String b = "b";
        return a + b;
    }

    public static void main(String[] args) {
        long tStart, tElapsed;

        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method with finals took " + tElapsed + " ms");

        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testNonFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method without finals took " + tElapsed + " ms");

    }

}

Le résultat?

Method with finals took 5 ms
Method without finals took 273 ms

Testé sur Java Hotspot VM 1.7.0_45-b18.

Alors, quelle est l'amélioration réelle des performances? Je n'ose pas dire. Dans la plupart des cas, probablement marginaux (~ 270 nanosecondes dans ce test synthétique car la concaténation de chaînes est totalement évitée - un cas rare), mais dans un code utilitaire hautement optimisé, cela pourrait être un facteur. Dans tous les cas, la réponse à la question d'origine est oui, cela pourrait améliorer les performances, mais au mieux marginalement .

Mis à part les avantages à la compilation, je n'ai trouvé aucune preuve que l'utilisation du mot clé finalait un effet mesurable sur les performances.

rustyx
la source
2
J'ai réécrit un peu votre code pour tester les deux cas 100 fois. Finalement, le temps moyen de la finale était de 0 ms et de 9 ms pour la non finale. L'augmentation du nombre d'itérations à 10 M définit la moyenne sur 0 ms et 75 ms. Le meilleur run pour la non finale était cependant de 0 ms. Peut-être que c'est la VM qui détecte que les résultats sont simplement jetés ou quelque chose? Je ne sais pas, mais peu importe, l'utilisation de la finale fait une différence significative.
Casper Færgemand
5
Test défectueux. Les tests antérieurs réchaufferont la JVM et bénéficieront des invocations de test ultérieures. Réorganisez vos tests et voyez ce qui se passe. Vous devez exécuter chaque test dans sa propre instance JVM.
Steve Kuo
16
Non le test n'est pas imparfait, l'échauffement a été pris en compte. Le deuxième test est plus lent, pas plus rapide. Sans échauffement, le deuxième test serait MÊME PLUS LENT.
rustyx
6
Dans testFinal (), tout le temps a renvoyé le même objet, à partir du pool de chaînes, car la résustation des chaînes finales et la concaténation des chaînes littérales sont évaluées au moment de la compilation. testNonFinal () chaque fois que retourne un nouvel objet, cela explique la différence de vitesse.
anber
4
Qu'est-ce qui vous fait penser que le scénario est irréaliste? Stringla concaténation est une opération beaucoup plus coûteuse que l'ajout Integers. Le faire statiquement (si possible) est plus efficace, c'est ce que montre le test.
rustyx
62

Oui il peut. Voici un exemple où final peut augmenter les performances:

La compilation conditionnelle est une technique dans laquelle les lignes de code ne sont pas compilées dans le fichier de classe en fonction d'une condition particulière. Cela peut être utilisé pour supprimer des tonnes de code de débogage dans une version de production.

considérer ce qui suit:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (doSomething) {
       // do first part. 
    }

    if (doSomething) {
     // do second part. 
    }

    if (doSomething) {     
      // do third part. 
    }

    if (doSomething) {
    // do finalization part. 
    }
}

En convertissant l'attribut doSomething en attribut final, vous avez indiqué au compilateur que chaque fois qu'il voit doSomething, il doit le remplacer par false conformément aux règles de substitution au moment de la compilation. La première passe du compilateur change le code en quelque chose comme ceci:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (false){
       // do first part. 
    }

    if (false){
     // do second part. 
    }

    if (false){
      // do third part. 
    }

    if (false){
    // do finalization part. 

    }
}

Une fois cela fait, le compilateur l'examine de nouveau et voit qu'il y a des instructions inaccessibles dans le code. Puisque vous travaillez avec un compilateur de qualité supérieure, il n'aime pas tous ces codes d'octets inaccessibles. Donc, cela les supprime, et vous vous retrouvez avec ceci:

public class ConditionalCompile {


  private final static boolean doSomething= false;

  public static void someMethodBetter( ) {

    // do first part. 

    // do second part. 

    // do third part. 

    // do finalization part. 

  }
}

réduisant ainsi tout code excessif ou toute vérification conditionnelle inutile.

Modifier: à titre d'exemple, prenons le code suivant:

public class Test {
    public static final void main(String[] args) {
        boolean x = false;
        if (x) {
            System.out.println("x");
        }
        final boolean y = false;
        if (y) {
            System.out.println("y");
        }
        if (false) {
            System.out.println("z");
        }
    }
}

Lors de la compilation de ce code avec Java 8 et de la décompilation avec javap -c Test.classnous obtenons:

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static final void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: ifeq          14
       6: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       9: ldc           #22                 // String x
      11: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      14: iconst_0
      15: istore_2
      16: return
}

Nous pouvons noter que le code compilé comprend uniquement la variable non finale x. Cela prouve que les variables finales ont un impact sur les performances, au moins pour ce cas simple.

mel3kings
la source
1
@ ŁukaszLech J'ai appris cela d'un livre d'Oreilly: Hardcore Java, sur leur chapitre concernant le mot-clé final.
mel3kings
15
Cela parle d'optimisation au moment de la compilation, cela signifie que le développeur connaît la VALEUR de la variable booléenne finale au moment de la compilation, quel est l'intérêt d'écrire si des blocs en premier lieu alors pour ce scénario où les IF-CONDITIONS ne sont pas nécessaires et ne font pas aucun sens? À mon avis, même si cela améliore les performances, il s'agit en premier lieu d'un mauvais code et peut être optimisé par le développeur lui-même plutôt que de confier la responsabilité au compilateur et la question vise principalement à poser des questions sur les améliorations des performances dans les codes habituels où final est utilisé, ce qui fait sens programmatique.
Bhavesh Agarwal
7
Le point de cela serait d'ajouter des instructions de débogage comme l'a déclaré mel3kings. Vous pouvez retourner la variable avant une génération de production (ou la configurer dans vos scripts de génération) et supprimer automatiquement tout ce code lors de la création de la distribution.
Adam
16

Je suis étonné que personne n'ait réellement publié de code réel décompilé pour prouver qu'il y a au moins quelques différences mineures.

Pour référence, cela a été testé par rapport à la javacversion 8, 9et 10.

Supposons que cette méthode:

public static int test() {
    /* final */ Object left = new Object();
    Object right = new Object();

    return left.hashCode() + right.hashCode();
}

Compiler ce code tel qu'il est, produit le exacte même code d'octets que quand finalaurait été présent (final Object left = new Object(); ).

Mais celui-ci:

public static int test() {
    /* final */ int left = 11;
    int right = 12;
    return left + right;
}

Produit:

   0: bipush        11
   2: istore_0
   3: bipush        12
   5: istore_1
   6: iload_0
   7: iload_1
   8: iadd
   9: ireturn

Le fait finald'être présent produit:

   0: bipush        12
   2: istore_1
   3: bipush        11
   5: iload_1
   6: iadd
   7: ireturn

Le code est assez explicite, dans le cas où il y a une constante de temps de compilation, il sera chargé directement sur la pile d'opérandes (il ne sera pas stocké dans le tableau de variables locales comme l'exemple précédent le fait via bipush 12; istore_0; iload_0) - ce qui a du sens puisque personne ne peut le changer.

D'un autre côté, pourquoi dans le deuxième cas le compilateur ne produit istore_0 ... iload_0pas me dépasse, ce n'est pas comme si cet emplacement 0était utilisé de quelque manière que ce soit (cela pourrait réduire le tableau de variables de cette façon, mais il peut y avoir des détails internes manquants, je ne peux pas dire à coup sûr)

J'ai été surpris de voir une telle optimisation, compte tenu du fait que les plus petits le javacfont. Quant à devrions-nous toujours utiliser final? Je ne vais même pas écrire un JMHtest (que je voulais au départ), je suis sûr que le diff est de l'ordre de ns(si possible à capturer du tout). Le seul endroit où cela pourrait être un problème, c'est quand une méthode n'a pas pu être insérée à cause de sa taille (et déclarerfinal réduirait cette taille de quelques octets).

Il y a deux autres finalpoints qui doivent être résolus. Tout d'abord, lorsqu'une méthode est final(d'un JITpoint de vue), une telle méthode est monomorphe - et ce sont les plus appréciées par leJVM .

Ensuite, il y a les finalvariables d'instance (qui doivent être définies dans chaque constructeur); ceux-ci sont importants car ils garantiront une référence correctement publiée, comme touché un peu ici et également spécifié exactement par le JLS.

Eugène
la source
J'ai compilé le code en utilisant Java 8 (JDK 1.8.0_162) avec les options de débogage ( javac -g FinalTest.java), décompilé le code en utilisant javap -c FinalTest.classet n'ai pas obtenu les mêmes résultats (avec final int left=12, j'ai eu bipush 11; istore_0; bipush 12; istore_1; bipush 11; iload_1; iadd; ireturn). Alors oui, le bytecode généré dépend de nombreux facteurs et il est difficile de dire si cela a finalou non un effet sur les performances. Mais comme le bytecode est différent, une différence de performance peut exister.
Julien Kronegg
13

Vous posez vraiment des questions sur deux (au moins) cas différents:

  1. final pour les variables locales
  2. final pour les méthodes / classes

Jon Skeet a déjà répondu 2). Environ 1):

Je ne pense pas que cela fasse une différence; pour les variables locales, le compilateur peut déduire si la variable est finale ou non (simplement en vérifiant si elle est affectée plusieurs fois). Donc, si le compilateur souhaite optimiser les variables qui ne sont attribuées qu'une seule fois, il peut le faire, que la variable soit réellement déclarée finalou non.

final pourrait faire une différence pour les champs de classe protégés / publics; là, il est très difficile pour le compilateur de savoir si le champ est défini plusieurs fois, car cela peut arriver à partir d'une classe différente (qui peut même ne pas avoir été chargée). Mais même dans ce cas, la JVM pourrait utiliser la technique décrite par Jon (optimiser de manière optimiste, revenir en arrière si une classe est chargée, ce qui change le champ).

En résumé, je ne vois aucune raison pour laquelle cela devrait améliorer les performances. Il est donc peu probable que ce type de micro-optimisation aide. Vous pouvez essayer de le comparer pour vous en assurer, mais je doute que cela fasse une différence.

Éditer:

En fait, selon la réponse de Timo Westkämper, dans certains cas , les performances des champs de classe final peuvent être améliorées. Je me suis trompé.

sleske
la source
Je ne pense pas que le compilateur puisse vérifier correctement le nombre de fois qu'une variable locale est affectée: qu'en est-il des structures if-then-else avec de nombreuses affectations?
gyorgyabraham
1
@gyabraham: Le compilateur vérifie déjà ces cas si vous déclarez une variable locale comme final, pour vous assurer de ne pas l'attribuer deux fois. Pour autant que je puisse voir, la même logique de vérification peut être (et est probablement) utilisée pour vérifier si une variable pourrait l'être final.
sleske
La finalité d'une variable locale n'est pas exprimée dans le bytecode, donc la JVM ne sait même pas qu'elle était finale
Steve Kuo
1
@SteveKuo: Même s'il n'est pas exprimé dans le bytecode, cela peut aider javacà mieux l'optimiser. Mais ce n'est que de la spéculation.
sleske
1
Le compilateur pourrait savoir si une variable locale a été affectée exactement une fois, mais en pratique, ce n'est pas le cas (au-delà de la vérification des erreurs). D'un autre côté, si une finalvariable est d'un type ou d'un type primitif Stringet est immédiatement affectée d'une constante de compilation comme dans l'exemple de la question, le compilateur doit l' inclure, car la variable est une constante de compilation par spécification. Mais pour la plupart des cas d'utilisation, le code peut sembler différent, mais cela ne fait toujours aucune différence que la constante soit en ligne ou lue à partir d'une variable locale en termes de performances.
Holger
6

Remarque: pas un expert java

Si je me souviens bien de ma java, il y aurait très peu de moyen d'améliorer les performances en utilisant le mot-clé final. J'ai toujours su qu'il existait pour le «bon code» - conception et lisibilité.

Neowizard
la source
1

Je ne suis pas un expert, mais je suppose que vous devez ajouter un finalmot clé à la classe ou à la méthode s'il ne sera pas écrasé et laisser les variables seules. S'il existe un moyen d'optimiser de telles choses, le compilateur le fera pour vous.

Crozin
la source
1

En fait, en testant du code lié à OpenGL, j'ai trouvé que l'utilisation du dernier modificateur sur un champ privé pouvait dégrader les performances. Voici le début de la classe que j'ai testée:

public class ShaderInput {

    private /* final */ float[] input;
    private /* final */ int[] strides;


    public ShaderInput()
    {
        this.input = new float[10];
        this.strides = new int[] { 0, 4, 8 };
    }


    public ShaderInput x(int stride, float val)
    {
        input[strides[stride] + 0] = val;
        return this;
    }

    // more stuff ...

Et c'est la méthode que j'ai utilisée pour tester les performances de diverses alternatives, parmi lesquelles la classe ShaderInput:

public static void test4()
{
    int arraySize = 10;
    float[] fb = new float[arraySize];
    for (int i = 0; i < arraySize; i++) {
        fb[i] = random.nextFloat();
    }
    int times = 1000000000;
    for (int i = 0; i < 10; ++i) {
        floatVectorTest(times, fb);
        arrayCopyTest(times, fb);
        shaderInputTest(times, fb);
        directFloatArrayTest(times, fb);
        System.out.println();
        System.gc();
    }
}

Après la 3e itération, avec la VM réchauffée, j'ai toujours obtenu ces chiffres sans le mot clé final:

Simple array copy took   : 02.64
System.arrayCopy took    : 03.20
ShaderInput took         : 00.77
Unsafe float array took  : 05.47

Avec le mot-clé final:

Simple array copy took   : 02.66
System.arrayCopy took    : 03.20
ShaderInput took         : 02.59
Unsafe float array took  : 06.24

Notez les chiffres du test ShaderInput.

Peu importait que je rende les champs publics ou privés.

Soit dit en passant, il y a quelques autres choses déconcertantes. La classe ShaderInput surpasse toutes les autres variantes, même avec le mot-clé final. C'est remarquable car il s'agit essentiellement d'une classe enveloppant un tableau flottant, tandis que les autres tests manipulent directement le tableau. Je dois comprendre celui-ci. Peut avoir quelque chose à voir avec l'interface fluide de ShaderInput.

De plus, System.arrayCopy est apparemment plus lent pour les petits tableaux que de simplement copier des éléments d'un tableau à l'autre dans une boucle for. Et l'utilisation de sun.misc.Unsafe (ainsi que de java.nio.FloatBuffer direct, non illustré ici) fonctionne de façon catastrophique.

user3663845
la source
1
Vous avez oublié de rendre les paramètres définitifs. <pre> <code> public ShaderInput x (final int stride, final float val) {input [strides [stride] + 0] = val; retourner ceci; } </code> </pre> D'après mes expériences, faire n'importe quelle variable ou champ final peut en effet augmenter les performances.
Anticro
1
Oh, et rendez aussi les autres finaux: <pre> <code> final int arraySize = 10; float final [] fb = new float [arraySize]; for (int i = 0; i <arraySize; i ++) {fb [i] = random.nextFloat (); } final int times = 1000000000; for (int i = 0; i <10; ++ i) {floatVectorTest (times, fb); arrayCopyTest (times, fb); shaderInputTest (times, fb); directFloatArrayTest (fois, fb); System.out.println (); System.gc (); } </code> </pre>
Anticro
1

La finale (au moins pour les variables et les paramètres des membres) est plus pour les humains que pour la machine.

Il est recommandé de rendre les variables définitives dans la mesure du possible. Je souhaite que Java ait rendu les "variables" finales par défaut et avait un mot-clé "Mutable" pour autoriser les changements. Les classes immuables conduisent à un code threadé bien meilleur, et le simple fait de jeter un coup d'œil à une classe avec "final" devant chaque membre montrera rapidement qu'elle est immuable.

Un autre cas - j'ai converti beaucoup de code pour utiliser les annotations @ NonNull / @ Nullable (Vous pouvez dire qu'un paramètre de méthode ne doit pas être nul alors l'IDE peut vous avertir chaque fois que vous passez une variable qui n'est pas étiquetée @ Non nul - le tout se propage à un degré ridicule). Il est beaucoup plus facile de prouver qu'une variable ou un paramètre membre ne peut pas être nul lorsqu'il est marqué comme final, car vous savez qu'il n'est pas réaffecté ailleurs.

Ma suggestion est de prendre l'habitude d'appliquer la finale pour les membres et les paramètres par défaut, c'est juste quelques caractères mais vous poussera à améliorer votre style de codage si rien d'autre.

Final pour les méthodes ou les classes est un autre concept car il interdit une forme de réutilisation très valide et ne dit pas grand-chose au lecteur. La meilleure utilisation est probablement la façon dont ils ont fait la chaîne et les autres types intrinsèques finaux afin que vous puissiez compter sur un comportement cohérent partout - Cela a empêché beaucoup de bugs (bien qu'il y ait des fois où j'aurais AIMÉ étendre la chaîne ... oh le possibilités)

Bill K
la source
0

Comme mentionné ailleurs, «final» pour une variable locale, et dans une moindre mesure une variable membre, est plus une question de style.

'final' est une déclaration selon laquelle vous souhaitez que la variable ne change pas (c'est-à-dire que la variable ne variera pas!). Le compilateur peut alors vous aider en vous plaignant si vous violez votre propre contrainte.

Je partage le sentiment que Java aurait été un meilleur langage si les identifiants (je suis désolé, je ne peux pas appeler une chose non variable une `` variable '') étaient définitifs par défaut, et vous demandaient de dire explicitement qu'il s'agissait de variables. Mais cela dit, je n'utilise généralement pas «final» sur les variables locales qui sont initialisées et jamais assignées; cela semble trop bruyant.

(J'utilise final sur les variables membres)

user13752845
la source
-3

Les membres déclarés avec final seront disponibles tout au long du programme car contrairement aux non finaux, si ces membres n'ont pas été utilisés dans le programme, ils ne seront pas pris en charge par Garbage Collector, ce qui peut entraîner des problèmes de performances en raison d'une mauvaise gestion de la mémoire.

nams
la source
2
Quel genre de non-sens est-ce? Avez-vous une source pour laquelle vous pensez que c'est le cas?
J. Doe
-4

final Le mot-clé peut être utilisé de cinq façons en Java.

  1. Une classe est finale
  2. Une variable de référence est finale
  3. Une variable locale est finale
  4. Une méthode est définitive

Une classe est finale: une classe est finale signifie que nous ne pouvons pas être étendus ou que l'héritage signifie que l'héritage n'est pas possible.

De même - Un objet est final: quelque temps nous ne modifions pas l'état interne de l'objet donc dans ce cas nous pouvons spécifier que l'objet est final object.object final signifie pas variable aussi final.

Une fois la variable de référence rendue définitive, elle ne peut pas être réaffectée à un autre objet. Mais peut changer le contenu de l'objet tant que ses champs ne sont pas définitifs

adityaraj
la source
2
Par "l'objet est définitif", vous entendez "l'objet est immuable".
gyorgyabraham
6
Vous avez raison, mais vous ne répondez pas à la question. OP n'a pas demandé quels finalmoyens, mais si l'utilisation finalinfluençait les performances.
Honza Zidek