Comment fonctionne le mot-clé «final» en Java? (Je peux toujours modifier un objet.)

480

En Java, nous utilisons un finalmot-clé avec des variables pour spécifier que ses valeurs ne doivent pas être modifiées. Mais je vois que vous pouvez changer la valeur dans le constructeur / méthodes de la classe. Encore une fois, si la variable l'est, staticc'est une erreur de compilation.

Voici le code:

import java.util.ArrayList;
import java.util.List;

class Test {
  private final List foo;

  public Test()
  {
      foo = new ArrayList();
      foo.add("foo"); // Modification-1
  }
  public static void main(String[] args) 
  {
      Test t = new Test();
      t.foo.add("bar"); // Modification-2
      System.out.println("print - " + t.foo);
  }
}

Le code ci-dessus fonctionne bien et aucune erreur.

Modifiez maintenant la variable comme suit static:

private static final List foo;

C'est maintenant une erreur de compilation. Comment ça finalmarche vraiment?

GS
la source
puisque foo n'est pas visible - comment pourrait-il être compilé?
Björn Hallström
5
@therealprashant ce n'est pas vrai. Les variables statiques privées sont valides, elles sont accessibles à partir de méthodes statiques à l'intérieur de la classe dans laquelle elles sont définies. Une variable statique signifie que la variable existe une fois et n'est pas liée à une instance d'une classe.
mbdavis
3
@mbdavis Oh oui! Merci. Mais je ne supprimerai toujours pas le commentaire pour aider les gens qui pensent comme moi et ensuite votre commentaire les fera réfléchir dans la bonne direction.
therealprashant
@therealprashant ok pas de soucis!
mbdavis

Réponses:

518

Vous êtes toujours autorisé à initialiser une finalvariable. Le compilateur s'assure que vous ne pouvez le faire qu'une seule fois.

Notez que l'appel de méthodes sur un objet stocké dans une finalvariable n'a rien à voir avec la sémantique de final. En d'autres termes: finalne concerne que la référence elle-même, et non le contenu de l'objet référencé.

Java n'a aucun concept d'immuabilité des objets; ceci est réalisé en concevant soigneusement l'objet, et est une entreprise loin d'être triviale.

Marko Topolnik
la source
12
essayez de faire t.foo = new ArrayList (); dans la méthode principale et vous obtiendrez une erreur de compilation ... la référence foo est liée à un seul objet final d'ArrayList ... elle ne peut pointer vers aucun autre ArrayList
Code2Interface
50
hmmm. C'est une question de référence et non de valeur. Merci!
GS
2
J'ai une question. Quelqu'un que je connais a déclaré "final" également que la variable soit stockée sur la pile. Est-ce correct? J'ai effectué des recherches partout et je n'ai trouvé aucune référence pouvant approuver ou refuser cette revendication. J'ai cherché sur la documentation Java et Android. Également recherché "modèle de mémoire Java". Peut-être que cela fonctionne de cette façon sur C / C ++, mais je ne pense pas que cela fonctionne de cette façon sur Java. Ai-je raison?
développeur Android
4
@androiddeveloper Rien en Java ne peut contrôler explicitement le placement de pile / tas. Plus précisément, le placement de pile tel que décidé par le compilateur HotSpot JIT est soumis à une analyse d'échappement , qui est beaucoup plus complexe que de vérifier si une variable l'est final. Les objets mutables peuvent également être alloués en pile. finalLes champs peuvent aider l'analyse d'échappement, cependant, mais c'est une route assez indirecte. Notez également que les variables finales ont un traitement identique à celles marquées finaldans le code source.
Marko Topolnik
5
finalest présent dans le fichier de classe et a des conséquences sémantiques importantes pour une optimisation de l'exécution. Il peut également entraîner des coûts car le JLS a une forte garantie sur la cohérence des finalchamps d'un objet. Par exemple, le processeur ARM doit utiliser une instruction de barrière de mémoire explicite à la fin de chaque constructeur d'une classe qui a des finalchamps. Sur d'autres processeurs, cela n'est toutefois pas nécessaire.
Marko Topolnik
574

Ceci est une question d'entrevue préférée . Avec ces questions, l'intervieweur essaie de savoir dans quelle mesure vous comprenez le comportement des objets par rapport aux constructeurs, aux méthodes, aux variables de classe (variables statiques) et aux variables d'instance.

import java.util.ArrayList;
import java.util.List;

class Test {
    private final List foo;

    public Test() {
        foo = new ArrayList();
        foo.add("foo"); // Modification-1
    }

    public void setFoo(List foo) {
       //this.foo = foo; Results in compile time error.
    }
}

Dans le cas ci-dessus, nous avons défini un constructeur pour «Test» et lui avons donné une méthode «setFoo».

A propos du constructeur: le constructeur ne peut être invoqué qu'une seule fois par création d'objet à l'aide du newmot - clé. Vous ne pouvez pas invoquer le constructeur plusieurs fois, car le constructeur n'est pas conçu pour le faire.

À propos de la méthode: une méthode peut être invoquée autant de fois que vous le souhaitez (même jamais) et le compilateur la connaît.

Scénario 1

private final List foo;  // 1

fooest une variable d' instance . Lorsque nous créons Testun objet de classe, la variable d'instance foosera copiée à l'intérieur de l'objet de Testclasse. Si nous affectons fooà l'intérieur du constructeur, le compilateur sait que le constructeur ne sera invoqué qu'une seule fois, il n'y a donc aucun problème à l'affecter à l'intérieur du constructeur.

Si nous affectons à l' foointérieur d'une méthode, le compilateur sait qu'une méthode peut être appelée plusieurs fois, ce qui signifie que la valeur devra être modifiée plusieurs fois, ce qui n'est pas autorisé pour une finalvariable. Le compilateur décide donc que le constructeur est un bon choix! Vous ne pouvez affecter une valeur à une variable finale qu'une seule fois.

Scénario 2

private static final List foo = new ArrayList();

fooest maintenant une variable statique . Lorsque nous créons une instance de Testclasse, foone sera pas copié dans l'objet car il fooest statique. N'est maintenant foopas une propriété indépendante de chaque objet. C'est une propriété de Testclasse. Mais foopeut être vu par plusieurs objets et si chaque objet qui est créé en utilisant le newmot - clé qui appellera finalement le Testconstructeur qui change la valeur au moment de la création de plusieurs objets (n'oubliez static foopas n'est pas copié dans chaque objet, mais est partagé entre plusieurs objets .)

Scénario 3

t.foo.add("bar"); // Modification-2

Ci Modification-2- dessus vient de votre question. Dans le cas ci-dessus, vous ne modifiez pas le premier objet référencé, mais vous ajoutez du contenu à l'intérieur fooqui est autorisé. Le compilateur se plaint si vous essayez d'affecter un new ArrayList()à la foovariable de référence.
Règle Si vous avez initialisé une finalvariable, vous ne pouvez pas la modifier pour faire référence à un autre objet. (Dans ce cas ArrayList)

les classes finales ne peuvent pas être sous-
classées Les méthodes finales ne peuvent pas être remplacées. (Cette méthode est en superclasse) les méthodes
finales peuvent remplacer. (Lisez ceci de manière grammaticale. Cette méthode est dans une sous-classe)

AmitG
la source
1
Juste pour être clair. Dans le scénario 2, dites-vous que ce fooparamètre serait défini plusieurs fois malgré la désignation finale s'il fooest défini dans la classe Test et que plusieurs instances de Test sont créées?
Rawr
N'a pas compris la dernière ligne du scénario 2: mais foopeut être .. plusieurs objets.) Est-ce à dire que si je crée plusieurs objets à la fois, quel objet initialise la variable finale dépend de l'exécution?
Saumya Suhagiya
1
Je pense qu'une façon utile de penser au scénario 3 est que vous attribuez finalà l'adresse mémoire référencée par foolaquelle est une ArrayList. Vous n'affectez pas finalà l'adresse mémoire référencée par le premier élément de foo(ou tout autre élément d'ailleurs). Par conséquent, vous ne pouvez pas changer foomais vous pouvez changer foo[0].
Pinkerton
@Rawr En l'état, le scénario 2 provoquerait une erreur de compilation à cause de foo = new ArrayList();- foofait référence à la variable statique car nous sommes dans la même classe.
flow2k
Je suis un développeur C ++ apprenant Java. Est-il sûr de penser finalà une variable comme le même constmot - clé en C ++?
Doug Barbieri
213

Le mot clé final peut être utilisé de plusieurs façons:

  • Une classe finale ne peut pas être sous-classée.
  • Une méthode finale ne peut pas être remplacée par des sous-classes
  • Une variable finale ne peut être initialisée qu'une seule fois

Autre utilisation:

  • Lorsqu'une classe interne anonyme est définie dans le corps d'une méthode, toutes les variables déclarées finales dans la portée de cette méthode sont accessibles depuis la classe interne

Une variable de classe statique existera dès le début de la JVM et devrait être initialisée dans la classe. Le message d'erreur n'apparaîtra pas si vous procédez ainsi.

czupe
la source
24
C'est de loin ma réponse préférée. C'est simple et direct, c'est ce que je m'attends à lire dans les documents en ligne sur java.
RAnders00
Donc, dans les variables statiques, nous pouvons initialiser autant de fois que nous le voulons?
jorge saraiva
1
@jorgesaraiva oui, les variables statiques ne sont pas des constantes.
czupe
1
@jorgesaraiva Vous pouvez attribuer (et non initialiser ) des staticchamps (tant qu'ils ne le sont pas final) autant de fois que vous le souhaitez. Voir ce wiki pour la différence entre l' affectation et l' initialisation .
56

Le finalmot-clé peut être interprété de deux manières différentes en fonction de son utilisation:

Types de valeurs: pour ints, doubles etc., il garantira que la valeur ne peut pas changer,

Types de référence: pour les références aux objets, finalgarantit que la référence ne changera jamais, ce qui signifie qu'elle fera toujours référence au même objet. Il ne fait aucune garantie que les valeurs à l'intérieur de l'objet référencé restent inchangées.

En tant que tel, final List<Whatever> foo;garantit que se fooréfère toujours à la même liste, mais le contenu de cette liste peut changer au fil du temps.

Smallhacker
la source
23

Si vous rendez foostatique, vous devez l'initialiser dans le constructeur de classe (ou en ligne où vous le définissez) comme les exemples suivants.

Constructeur de classe (pas d'instance):

private static final List foo;

static
{
   foo = new ArrayList();
}

En ligne:

private static final List foo = new ArrayList();

Le problème ici n'est pas comment fonctionne le finalmodificateur, mais plutôt comment fonctionne le staticmodificateur.

Le finalmodificateur impose une initialisation de votre référence au moment où l'appel à votre constructeur se termine (c'est-à-dire que vous devez l'initialiser dans le constructeur).

Lorsque vous initialisez un attribut en ligne, il est initialisé avant l'exécution du code que vous avez défini pour le constructeur, vous obtenez donc les résultats suivants:

  • si fooc'est static, foo = new ArrayList()sera exécuté avant l'exécution du static{}constructeur que vous avez défini pour votre classe
  • si foon'est pas static, foo = new ArrayList()sera exécutée avant que votre constructeur est géré

Lorsque vous n'initialisez pas un attribut en ligne, le finalmodificateur vous oblige à l'initialiser et à le faire dans le constructeur. Si vous avez également un staticmodificateur, le constructeur vous devrez initialiser l'attribut est la classe bloc d'initialisation: static{}.

L'erreur que vous obtenez dans votre code provient du fait qu'il static{}est exécuté lorsque la classe est chargée, avant le moment où vous instanciez un objet de cette classe. Ainsi, vous n'aurez pas initialisé foolors de la création de la classe.

Considérez le static{}bloc comme un constructeur pour un objet de type Class. C'est là que vous devez faire l'initialisation de vos static finalattributs de classe (si ce n'est pas fait en ligne).

Note latérale:

Le finalmodificateur assure la constance uniquement pour les types et références primitifs.

Lorsque vous déclarez un finalobjet, vous obtenez une final référence à cet objet, mais l'objet lui-même n'est pas constant.

Ce que vous réalisez vraiment en déclarant un finalattribut, c'est que, une fois que vous déclarez un objet pour votre objectif spécifique (comme celui final Listque vous avez déclaré), cet objet et seulement cet objet sera utilisé à cette fin: vous ne pourrez pas passer List fooà un autre List, mais vous pouvez toujours le modifier Listen ajoutant / supprimant des éléments (ceux que Listvous utilisez seront les mêmes, mais avec un contenu modifié).

lucian.pantelimon
la source
8

Ceci est une très bonne question d'entrevue. Parfois, ils peuvent même vous demander quelle est la différence entre un objet final et un objet immuable.

1) Lorsque quelqu'un mentionne un objet final, cela signifie que la référence ne peut pas être modifiée, mais son état (variables d'instance) peut être modifié.

2) Un objet immuable est un objet dont l'état ne peut pas être modifié, mais sa référence peut être modifiée. Ex:

    String x = new String("abc"); 
    x = "BCG";

La variable ref x peut être modifiée pour pointer une chaîne différente, mais la valeur de "abc" ne peut pas être modifiée.

3) Les variables d'instance (champs non statiques) sont initialisées lorsqu'un constructeur est appelé. Ainsi, vous pouvez initialiser des valeurs à vos variables à l'intérieur d'un constructeur.

4) "Mais je vois que vous pouvez changer la valeur dans le constructeur / les méthodes de la classe". - Vous ne pouvez pas le modifier à l'intérieur d'une méthode.

5) Une variable statique est initialisée lors du chargement de classe. Vous ne pouvez donc pas initialiser à l'intérieur d'un constructeur, cela doit être fait avant même. Vous devez donc affecter des valeurs à une variable statique lors de la déclaration elle-même.

user892871
la source
7

Le finalmot-clé en java est utilisé pour restreindre l'utilisateur. Le finalmot-clé java peut être utilisé dans de nombreux contextes. La finale peut être:

  1. variable
  2. méthode
  3. classe

Le finalmot-clé peut être appliqué avec les variables, une finalvariable qui n'a pas de valeur, est appelée finalvariable vide ou finalvariable non initialisée. Il peut être initialisé uniquement dans le constructeur. La finalvariable vide peut staticégalement être qui sera initialisée dans le staticbloc uniquement.

Variable finale Java:

Si vous créez une variable as final, vous ne pouvez pas modifier la valeur de la finalvariable (elle sera constante).

Exemple de finalvariable

Il y a une limite de vitesse de la variable finale, nous allons changer la valeur de cette variable, mais elle ne peut pas être modifiée car la variable finale une fois affectée à une valeur ne peut jamais être modifiée.

class Bike9{  
    final int speedlimit=90;//final variable  
    void run(){  
        speedlimit=400;  // this will make error
    }  

    public static void main(String args[]){  
    Bike9 obj=new  Bike9();  
    obj.run();  
    }  
}//end of class  

Classe finale Java:

Si vous créez une classe as final, vous ne pouvez pas l'étendre .

Exemple de classe finale

final class Bike{}  

class Honda1 extends Bike{    //cannot inherit from final Bike,this will make error
  void run(){
      System.out.println("running safely with 100kmph");
   }  

  public static void main(String args[]){  
      Honda1 honda= new Honda();  
      honda.run();  
      }  
  }  

Méthode finale Java:

Si vous définissez une méthode comme définitive, vous ne pouvez pas la remplacer .

Exemple de finalméthode (run () dans Honda ne peut pas remplacer run () dans Bike)

class Bike{  
  final void run(){System.out.println("running");}  
}  

class Honda extends Bike{  
   void run(){System.out.println("running safely with 100kmph");}  

   public static void main(String args[]){  
   Honda honda= new Honda();  
   honda.run();  
   }  
}  

partagé depuis: http://www.javatpoint.com/final-keyword

Ali Ziaee
la source
7

Il convient de mentionner quelques définitions simples:

Cours / Méthodes

Vous pouvez déclarer certaines ou toutes les méthodes d'une classe comme final, afin d'indiquer que la méthode ne peut pas être remplacée par des sous-classes.

Variables

Une fois qu'une finalvariable a été initialisée, elle contient toujours la même valeur.

final évitez essentiellement d'écraser / remplacer par quoi que ce soit (sous-classes, variable "réaffecter"), selon le cas.

ivanleoncz
la source
1
Je pense que la définition finale des variables est un peu courte; "En Java, lorsque le mot clé final est utilisé avec une variable de types de données primitifs (int, float, .. etc.), la valeur de la variable ne peut pas être modifiée, mais lorsque final est utilisé avec des variables non primitives (notez que les variables non primitives sont toujours des références à des objets en Java), les membres de l'objet référencé peuvent être modifiés. final pour les variables non primitives signifie simplement qu'ils ne peuvent pas être modifiés pour faire référence à un autre objet ". geeksforgeeks.org/g-fact-48
ceyun
Également valable, spécialement pour mentionner comme cas primitifs et non primitifs. Tks.
ivanleoncz
4

finalest un mot clé réservé en Java pour restreindre l'utilisateur et il peut être appliqué aux variables membres, aux méthodes, à la classe et aux variables locales. Les variables finales sont souvent déclarées avec le staticmot - clé en Java et sont traitées comme des constantes. Par exemple:

public static final String hello = "Hello";

Lorsque nous utilisons le finalmot - clé avec une déclaration de variable, la valeur stockée à l'intérieur de cette variable ne peut pas être modifiée ultérieurement.

Par exemple:

public class ClassDemo {
  private final int var1 = 3;
  public ClassDemo() {
    ...
  }
}

Remarque : Une classe déclarée comme finale ne peut pas être étendue ou héritée (c'est-à-dire qu'il ne peut pas y avoir de sous-classe de la super classe). Il est également bon de noter que les méthodes déclarées comme finales ne peuvent pas être remplacées par des sous-classes.

Les avantages de l'utilisation du mot-clé final sont abordés dans ce fil .

Desta Haileselassie Hagos
la source
2
the value stored inside that variable cannot be changed latterest partiellement vrai. Cela est vrai uniquement pour les types de données primitifs. Dans le cas où un objet est créé car final, comme arraylist, sa valeur peut changer mais pas la référence. Je vous remercie!
GS
3

Supposons que vous ayez deux tirelires, rouge et blanc. Vous attribuez à ces tirelires seulement deux enfants et ils ne sont pas autorisés à échanger leurs tiroirs. Vous avez donc des tirelires rouges ou blanches (final) vous ne pouvez pas modifier la boîte mais vous pouvez mettre de l'argent sur votre boîte. Personne ne s'en soucie (Modification-2).

huseyin
la source
2

Lisez toutes les réponses.

Il existe un autre cas d'utilisation où le finalmot-clé peut être utilisé, c'est-à-dire dans un argument de méthode:

public void showCaseFinalArgumentVariable(final int someFinalInt){

   someFinalInt = 9; // won't compile as the argument is final

}

Peut être utilisé pour une variable qui ne doit pas être modifiée.

Pritam Banerjee
la source
1

Lorsque vous le rendez final statique, il doit être initialisé dans un bloc d'initialisation statique

    private static final List foo;

    static {
        foo = new ArrayList();
    }

    public Test()
    {
//      foo = new ArrayList();
        foo.add("foo"); // Modification-1
    }
Evgeniy Dorofeev
la source
1

Le finalmot-clé indique qu'une variable ne peut être initialisée qu'une seule fois. Dans votre code, vous n'effectuez qu'une seule initialisation de final afin que les conditions soient satisfaites. Cette instruction effectue la seule initialisation de foo. Notez que final! = Immuable, cela signifie seulement que la référence ne peut pas changer.

foo = new ArrayList();

Lorsque vous déclarez fooque static finalla variable doit être initialisée lorsque la classe est chargée et ne peut pas s'appuyer sur l'instanciation (alias appel au constructeur) pour s'initialiser foocar les champs statiques doivent être disponibles sans instance d'une classe. Il n'y a aucune garantie que le constructeur aura été appelé avant d'utiliser le champ statique.

Lorsque vous exécutez votre méthode dans le static finalscénario, la Testclasse est chargée avant l'instanciation tà ce moment, il n'y a pas d'instanciation foosignifiant qu'elle n'a pas été initialisée, elle fooest donc définie sur la valeur par défaut pour tous les objets null. À ce stade, je suppose que votre code génère un NullPointerExceptionlorsque vous essayez d'ajouter un élément à la liste.

Kevin Bowersox
la source
1

Tout d'abord, l'endroit dans votre code où vous initialisez (c'est-à-dire affectant pour la première fois) foo est ici:

foo = new ArrayList();

foo est un objet (avec le type List) donc c'est un type de référence , pas un type de valeur (comme int). En tant que tel, il contient une référence à un emplacement de mémoire (par exemple 0xA7D2A834) où vos éléments de liste sont stockés. Des lignes comme ça

foo.add("foo"); // Modification-1

ne changez pas la valeur de foo (qui, encore une fois, est juste une référence à un emplacement mémoire). Au lieu de cela, ils ajoutent simplement des éléments à cet emplacement de mémoire référencé. Pour violer le mot-clé final , vous devez essayer de réaffecter foo comme suit:

foo = new ArrayList();

Ce serait vous donner une erreur de compilation.


Maintenant, avec cela à l'écart, pensez à ce qui se passe lorsque vous ajoutez le mot clé statique .

Lorsque vous n'avez PAS le mot-clé statique, chaque objet qui instancie la classe a sa propre copie de foo. Par conséquent, le constructeur attribue une valeur à une nouvelle copie vierge de la variable foo, ce qui est parfaitement correct.

Cependant, lorsque vous AVEZ le mot-clé statique, un seul toto existe en mémoire qui est associé à la classe. Si vous deviez créer deux ou plusieurs objets, le constructeur tenterait de réaffecter ce foo à chaque fois, violant le mot-clé final .

Niko Bellic
la source
1
  1. Comme la variable finale n'est pas statique, elle peut être initialisée dans le constructeur. Mais si vous le rendez statique, il ne peut pas être initialisé par le constructeur (car les constructeurs ne sont pas statiques).
  2. L'ajout à la liste ne devrait pas s'arrêter en rendant la liste définitive. finallie simplement la référence à un objet particulier. Vous êtes libre de changer «l'état» de cet objet, mais pas l'objet lui-même.
Ankit
la source
1

Voici différents contextes où final est utilisé.

Variables finales Une variable finale ne peut être affectée qu'une seule fois. Si la variable est une référence, cela signifie que la variable ne peut pas être liée à nouveau pour référencer un autre objet.

class Main {
   public static void main(String args[]){
      final int i = 20;
      i = 30; //Compiler Error:cannot assign a value to final variable i twice
   }
}

la variable finale peut recevoir une valeur plus tard (pas obligatoire d'attribuer une valeur lorsqu'elle est déclarée), mais une seule fois.

Classes finales Une classe finale ne peut pas être étendue (héritée)

final class Base { }
class Derived extends Base { } //Compiler Error:cannot inherit from final Base

public class Main {
   public static void main(String args[]) {
   }
}

Méthodes finales Une méthode finale ne peut pas être remplacée par des sous-classes.

//Error in following program as we are trying to override a final method.
class Base {
  public final void show() {
       System.out.println("Base::show() called");
    }
}     
class Derived extends Base {
    public void show() {  //Compiler Error: show() in Derived cannot override
       System.out.println("Derived::show() called");
    }
}     
public class Main {
    public static void main(String[] args) {
        Base b = new Derived();;
        b.show();
    }
}
roottraveller
la source
1

J'ai pensé écrire une réponse mise à jour et approfondie ici.

final Le mot-clé peut être utilisé à plusieurs endroits.

  1. Des classes

A final classsignifie qu'aucune autre classe ne peut étendre cette classe finale. Lorsque Java Run Time ( JRE ) sait qu'une référence d'objet est dans le type d'une classe finale (disons F), il sait que la valeur de cette référence ne peut être que dans le type de F.

Ex:

F myF;
myF = new F();    //ok
myF = someOther;  //someOther cannot be in type of a child class of F.
                  //because F cannot be extended.

Ainsi, lorsqu'il exécute une méthode de cet objet, cette méthode n'a pas besoin d'être résolue au moment de l'exécution à l'aide d'une table virtuelle . c'est-à-dire que le polymorphisme d'exécution ne peut pas être appliqué. Donc, le temps d'exécution ne dérange pas à ce sujet. Cela signifie qu'il économise du temps de traitement, ce qui améliorera les performances.

  1. les méthodes

Un final methodde n'importe quelle classe signifie que toute classe enfant étendant cette classe ne peut pas remplacer cette ou ces méthodes finales. Ainsi, le comportement à l'exécution dans ce scénario est également tout à fait identique au comportement précédent que j'ai mentionné pour les classes.

  1. champs, variables locales, paramètres de méthode

Si l'on a spécifié tout type de ci-dessus comme final, cela signifie que la valeur est déjà finalisée, donc la valeur ne peut pas être modifiée .

Ex:

Pour les champs, paramètres locaux

final FinalClass fc = someFC; //need to assign straight away. otherwise compile error.
final FinalClass fc; //compile error, need assignment (initialization inside a constructor Ok, constructor can be called only once)
final FinalClass fc = new FinalClass(); //ok
fc = someOtherFC; //compile error
fc.someMethod(); //no problem
someOtherFC.someMethod(); //no problem

Pour les paramètres de méthode

void someMethod(final String s){
    s = someOtherString; //compile error
}

Cela signifie simplement que la valeur de la valeur de finalréférence ne peut pas être modifiée. c'est-à-dire qu'une seule initialisation est autorisée. Dans ce scénario, au moment de l'exécution, étant donné que JRE sait que les valeurs ne peuvent pas être modifiées, il charge toutes ces valeurs finalisées (des références finales) dans le cache L1 . Parce qu'il n'a pas besoin de se recharger encore et encore depuis la mémoire principale . Sinon, il se charge dans le cache L2 et effectue de temps en temps un chargement à partir de la mémoire principale. C'est donc aussi une amélioration des performances.

Donc, dans les trois scénarios ci-dessus, lorsque nous n'avons pas spécifié le finalmot - clé aux endroits que nous pouvons utiliser, nous n'avons pas à nous inquiéter, les optimisations du compilateur le feront pour nous. Il y a aussi beaucoup d'autres choses que les optimisations du compilateur font pour nous. :)

Supun Wijerathne
la source
0

Surtout sont corrects. De plus, si vous ne voulez pas que d'autres créent des sous-classes à partir de votre classe, déclarez votre classe comme finale. Ensuite, il devient le niveau feuille de votre hiérarchie d'arbre de classe que personne ne peut étendre davantage. C'est une bonne pratique pour éviter une hiérarchie énorme des classes.

Shehan Simen
la source