547 votes

Comment final œuvres de mot clé

En java, nous utilisons final mot clé de variables pour faire de ses valeurs, de ne pas être changé. Mais je vois que vous pouvez modifier la valeur dans le constructeur/méthodes de la classe. Encore une fois, si la variable est - static alors que c'est une erreur de compilation.

Voici le code:

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 très bien et sans erreurs.

Maintenant, modifiez la variable static:

private static final List foo;

Maintenant, c'est une erreur de compilation. Comment est-ce final fonctionne vraiment?

632voto

AmitG Points 2060

C'est favorite question d'entrevue. Intervieweur essaie de trouver ici, à quel point vous comprenez le comportement d'objets par rapport aux constructeurs, les méthodes, les variables de classe(variables statiques), les 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;  //compile time error.
    }
}

Dans le cas ci-dessus, nous avons défini Test constructeur et setFoo méthode.
À propos de constructeur: Constructeur ne peut être invoqué qu' une seule fois par la création d'un objet en utilisant new mot-clé. Programmeur ne peut invoquer le constructeur de nombreuses fois à cause de constructeur sont conçus de telle sorte.
Sur la méthode: la Méthode peut être appelée autant de fois que le programmeur veut et le compilateur sait programmeur peut invoquer la méthode zéro ou plusieurs fois.

Scénario 1

private final List foo;  // 1

foo est une instance de la variable. Lorsque nous créons Test de la classe d'objet puis variable d'instance, foo sera copié à l'intérieur de l'objet de la classe de Test. Si nous cédons foo à l'intérieur de constructeur puis compilateur de savoir que le Constructeur sera appelé qu'une seule fois. donc, il n'y a pas de problème pour l'attribuer à l'intérieur de constructeur.

Si nous cédons foo à l'intérieur de la méthode puis compilateur sait que la méthode peut être invoqué plusieurs fois. Donc, la valeur devra être changé plusieurs fois ce qui n'est pas autorisé pour final variable. Vous pouvez assigner une valeur à la variable finale qu'une seule fois. Donc compilateur décide constructeur est un bon choix!

Scénario 2

private static final List foo = new ArrayList();

foo est maintenant statique de la variable. Lorsque nous créons un objet de Test classe foo ne seront pas copiés à l'objet de l' Test classe foo est statique. Maintenant, foo n'est pas la propriété de chaque objet. C'est la propriété de la classe de Test. Mais foo peut être vu par de nombreux objets et si chaque objet qui est créé à l'aide de mots clés, qui en fin de compte invoquer Test constructeur alors la valeur sera changé à la fois de multiples création de l'objet (Rappelez - static foo n'est pas copié dans chaque objet maintenant, mais est partagé entre plusieurs objets.)

Scénario 3

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

Dans le cas ci-dessus, vous n'êtes pas de modifier la première objet référencé, mais vous ajoutez du contenu à l'intérieur d' foo ce qui est permis. Le compilateur se plaint si vous essayez d'attribuer new ArrayList() objet à l' foo variable de référence.
La règle est que si vous avez initialisé objet d' final variable de référence vous ne pouvez pas le changer pour désigner les différents ArrayList objet. (dans ce cas ArrayList)

finale de la classe ne peut pas être sous-classé
finale méthodes ne peuvent pas être remplacées. (Cette méthode est dans la super-classe)
finale méthodes peuvent remplacer. (Lire cette grammaticale dans la manière. Cette méthode est décrite dans la sous-classe)

591voto

Marko Topolnik Points 77257

Vous êtes toujours autorisé à initialiser un final variable. Le compilateur permet de s'assurer que vous pouvez faire qu'une seule fois.

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

Java n'a pas de notion d'objet immutabilité; ceci est réalisé par l'soigneusement la conception de l'objet, et est loin de effort insignifiant.

238voto

czupe Points 737

Finale de mot a plusieurs façon de l'utiliser:

  • Une dernière classe ne peut pas être sous-classé.
  • Une dernière méthode ne peut pas être remplacée par des sous-classes
  • Une dernière variable ne peut être initialisé une fois

Autre utilisation:

  • Quand un anonyme intérieur de la classe est définie dans le corps d'une méthode, toutes les variables déclarées final dans le champ d'application de cette méthode sont accessible à partir de l'intérieur de la classe

Une classe statique variable existent depuis le début de la JVM, et doit être initialisé dans la classe. Le message d'erreur ne s'affiche pas si vous faites cela.

69voto

Smallhacker Points 2340

L' final mot-clé peut être interprété de deux manières différentes, selon qu'il est utilisé sur:

Types de données: Pour ints, doubles etc, il veillera à ce que la valeur ne peut pas changer,

Types de références: les références à des objets, final s'assure que la référence ne changera jamais, ce qui signifie qu'il va toujours se référer au même objet. Il ne donne aucune garantie que ce soit sur les valeurs à l'intérieur de l'objet visé à rester le même.

En tant que tel, final List foo; assure foo correspond toujours à la même liste, mais la liste peut changer au fil du temps.

24voto

lucian.pantelimon Points 1922

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

Le constructeur de la classe (pas d'exemple):

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 la façon dont l' final modificateur œuvres, mais plutôt comment l' static modificateur de travaux.

L' final modificateur applique à une initialisation de votre renvoi, par le temps de l'appel à votre constructeur complète (c'est à dire que vous devez l'initialiser dans le constructeur).

Lorsque vous initialisez un attribut en ligne, il est initialisé avant le code que vous avez définis pour le constructeur est exécuté, de sorte que vous obtenez les résultats suivants:

  • si foo est static, foo = new ArrayList() sera exécuté avant l' static{} constructeur, vous avez défini pour votre classe est exécutée
  • si foo n'est static, foo = new ArrayList() sera exécuté avant votre constructeur est exécuté

Lorsque vous n'avez pas initilize un attribut en ligne, final modificateur applique que si vous initialisez et que vous devez le faire dans le constructeur. Si vous aussi vous avez un static modificateur, le constructeur, vous devrez initialiser l'attribut dans la classe' l'initialisation du bloc : static{}.

L'erreur que vous obtenez dans votre code est le fait qu' static{} est exécuté lorsque la classe est chargée, avant le moment d'instancier un objet de cette classe. Ainsi, vous n'avez pas initialisé foo lorsque la classe est créée.

Pensez à l' static{} bloc comme un constructeur pour un objet de type Class. C'est là que vous devez effectuer l'initialisation de votre static final attributs de classe (si pas fait inline).

Note de côté:

L' final modificateur assure const-ness seulement pour les types primitifs et les références.

Lorsque vous déclarez une final de l'objet, ce que vous obtenez est un final de référence pour cet objet, mais l'objet lui-même n'est pas constante.

Ce que vous êtes vraiment à atteindre lors de la déclaration d'un final attribut est que, une fois que vous déclarez un objet pour votre but précis (comme l' final List que vous avez déclaré), et uniquement à cet objet sera utilisé à cette fin: vous ne serez pas en mesure de changer de List foo autre List, mais vous pouvez toujours modifier votre List par l'ajout/suppression d'éléments ( List vous utilisez sera le même, seule avec son contenu modifié).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X