En Java, nous utilisons un final
mot-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, static
c'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 final
marche vraiment?
Réponses:
Vous êtes toujours autorisé à initialiser une
final
variable. 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
final
variable n'a rien à voir avec la sémantique definal
. En d'autres termes:final
ne 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.
la source
final
. Les objets mutables peuvent également être alloués en pile.final
Les 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éesfinal
dans le code source.final
est 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 desfinal
champs 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 desfinal
champs. Sur d'autres processeurs, cela n'est toutefois pas nécessaire.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.
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
new
mot - 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
foo
est une variable d' instance . Lorsque nous créonsTest
un objet de classe, la variable d'instancefoo
sera copiée à l'intérieur de l'objet deTest
classe. Si nous affectonsfoo
à 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'
foo
inté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 unefinal
variable. 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
foo
est maintenant une variable statique . Lorsque nous créons une instance deTest
classe,foo
ne sera pas copié dans l'objet car ilfoo
est statique. N'est maintenantfoo
pas une propriété indépendante de chaque objet. C'est une propriété deTest
classe. Maisfoo
peut être vu par plusieurs objets et si chaque objet qui est créé en utilisant lenew
mot - clé qui appellera finalement leTest
constructeur qui change la valeur au moment de la création de plusieurs objets (n'oubliezstatic foo
pas n'est pas copié dans chaque objet, mais est partagé entre plusieurs objets .)Scénario 3
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érieurfoo
qui est autorisé. Le compilateur se plaint si vous essayez d'affecter unnew ArrayList()
à lafoo
variable de référence.Règle Si vous avez initialisé une
final
variable, vous ne pouvez pas la modifier pour faire référence à un autre objet. (Dans ce casArrayList
)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)
la source
foo
paramètre serait défini plusieurs fois malgré la désignation finale s'ilfoo
est défini dans la classe Test et que plusieurs instances de Test sont créées?foo
peut ê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?final
à l'adresse mémoire référencée parfoo
laquelle est une ArrayList. Vous n'affectez pasfinal
à l'adresse mémoire référencée par le premier élément defoo
(ou tout autre élément d'ailleurs). Par conséquent, vous ne pouvez pas changerfoo
mais vous pouvez changerfoo[0]
.foo = new ArrayList();
-foo
fait référence à la variable statique car nous sommes dans la même classe.final
à une variable comme le mêmeconst
mot - clé en C ++?Le mot clé final peut être utilisé de plusieurs façons:
Autre utilisation:
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.
la source
static
champs (tant qu'ils ne le sont pasfinal
) autant de fois que vous le souhaitez. Voir ce wiki pour la différence entre l' affectation et l' initialisation .Le
final
mot-clé peut être interprété de deux manières différentes en fonction de son utilisation:Types de valeurs: pour
int
s,double
s etc., il garantira que la valeur ne peut pas changer,Types de référence: pour les références aux objets,
final
garantit 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 sefoo
réfère toujours à la même liste, mais le contenu de cette liste peut changer au fil du temps.la source
Si vous rendez
foo
statique, 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):
En ligne:
Le problème ici n'est pas comment fonctionne le
final
modificateur, mais plutôt comment fonctionne lestatic
modificateur.Le
final
modificateur 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:
foo
c'eststatic
,foo = new ArrayList()
sera exécuté avant l'exécution dustatic{}
constructeur que vous avez défini pour votre classefoo
n'est passtatic
,foo = new ArrayList()
sera exécutée avant que votre constructeur est géréLorsque vous n'initialisez pas un attribut en ligne, le
final
modificateur vous oblige à l'initialiser et à le faire dans le constructeur. Si vous avez également unstatic
modificateur, 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éfoo
lors de la création de la classe.Considérez le
static{}
bloc comme un constructeur pour un objet de typeClass
. C'est là que vous devez faire l'initialisation de vosstatic final
attributs de classe (si ce n'est pas fait en ligne).Note latérale:
Le
final
modificateur assure la constance uniquement pour les types et références primitifs.Lorsque vous déclarez un
final
objet, vous obtenez unefinal
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
final
attribut, c'est que, une fois que vous déclarez un objet pour votre objectif spécifique (comme celuifinal List
que vous avez déclaré), cet objet et seulement cet objet sera utilisé à cette fin: vous ne pourrez pas passerList foo
à un autreList
, mais vous pouvez toujours le modifierList
en ajoutant / supprimant des éléments (ceux queList
vous utilisez seront les mêmes, mais avec un contenu modifié).la source
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:
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.
la source
Le
final
mot-clé en java est utilisé pour restreindre l'utilisateur. Lefinal
mot-clé java peut être utilisé dans de nombreux contextes. La finale peut être:Le
final
mot-clé peut être appliqué avec les variables, unefinal
variable qui n'a pas de valeur, est appeléefinal
variable vide oufinal
variable non initialisée. Il peut être initialisé uniquement dans le constructeur. Lafinal
variable vide peutstatic
également être qui sera initialisée dans lestatic
bloc uniquement.Variable finale Java:
Si vous créez une variable as
final
, vous ne pouvez pas modifier la valeur de lafinal
variable (elle sera constante).Exemple de
final
variableIl 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.
Classe finale Java:
Si vous créez une classe as
final
, vous ne pouvez pas l'étendre .Exemple de classe finale
Méthode finale Java:
Si vous définissez une méthode comme définitive, vous ne pouvez pas la remplacer .
Exemple de
final
méthode (run () dans Honda ne peut pas remplacer run () dans Bike)partagé depuis: http://www.javatpoint.com/final-keyword
la source
Il convient de mentionner quelques définitions simples:
Cours / Méthodes
Variables
final
évitez essentiellement d'écraser / remplacer par quoi que ce soit (sous-classes, variable "réaffecter"), selon le cas.la source
final
est 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 lestatic
mot - clé en Java et sont traitées comme des constantes. Par exemple:Lorsque nous utilisons le
final
mot - 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:
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 .
la source
the value stored inside that variable cannot be changed latter
est partiellement vrai. Cela est vrai uniquement pour les types de données primitifs. Dans le cas où un objet est créé carfinal
, comme arraylist, sa valeur peut changer mais pas la référence. Je vous remercie!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).
la source
Lisez toutes les réponses.
Il existe un autre cas d'utilisation où le
final
mot-clé peut être utilisé, c'est-à-dire dans un argument de méthode:Peut être utilisé pour une variable qui ne doit pas être modifiée.
la source
Lorsque vous le rendez final statique, il doit être initialisé dans un bloc d'initialisation statique
la source
Le
final
mot-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 defoo
. Notez quefinal
! = Immuable, cela signifie seulement que la référence ne peut pas changer.Lorsque vous déclarez
foo
questatic final
la 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'initialiserfoo
car 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 final
scénario, laTest
classe est chargée avant l'instanciationt
à ce moment, il n'y a pas d'instanciationfoo
signifiant qu'elle n'a pas été initialisée, ellefoo
est donc définie sur la valeur par défaut pour tous les objetsnull
. À ce stade, je suppose que votre code génère unNullPointerException
lorsque vous essayez d'ajouter un élément à la liste.la source
Tout d'abord, l'endroit dans votre code où vous initialisez (c'est-à-dire affectant pour la première fois) foo est ici:
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
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:
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 .
la source
final
lie 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.la source
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.
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)
Méthodes finales Une méthode finale ne peut pas être remplacée par des sous-classes.
la source
J'ai pensé écrire une réponse mise à jour et approfondie ici.
final
Le mot-clé peut être utilisé à plusieurs endroits.A
final class
signifie 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:
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.
Un
final method
de 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.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
Pour les paramètres de méthode
Cela signifie simplement que la valeur de la valeur de
final
ré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
final
mot - 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. :)la source
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.
la source