Pourquoi une variable finale doit-elle être initialisée avant la fin du constructeur?

Pourquoi une variable finale doit-elle être initialisée avant la fin du constructeur?

public class Ex { final int q; } 

Quand je comstack ce code je reçois une erreur comme ça

err: la variable q n’a peut-être pas été initialisée

La raison officielle est qu’elle est définie par la spécification de langage Java 8.3.1.2 :

Une variable d’instance finale vide doit être définitivement affectée à la fin de chaque constructeur de la classe dans laquelle elle est déclarée; sinon, une erreur de compilation survient.

Une finale vide est une variable finale dont la déclaration manque d’initialiseur (c’est-à-dire ce que vous décrivez).

Parce que final vous empêche de modifier les variables, il doit être initialisé à un moment donné et le constructeur est le bon endroit pour le faire.

Dans votre cas, il s’agirait d’une finale vierge car elle n’est pas initialisée lorsqu’elle est déclarée.

La valeur d’une variable final ne peut être définie qu’une seule fois. Le constructeur est le seul endroit dans le code pour une classe que vous pouvez garantir que cela sera vrai; le constructeur n’est appelé qu’une seule fois pour un object, mais d’autres méthodes peuvent être appelées n’importe quel nombre de fois.

Une variable final doit être initialisée à la déclaration ou dans un constructeur.

S’il n’a pas été initialisé lors du retour du constructeur, il se peut qu’il ne soit jamais initialisé et qu’il rest une variable non initialisée. Le compilateur ne peut pas prouver qu’il sera initialisé et génère donc une erreur.

Cet extrait de Wikipedia l’ explique bien:

Une variable finale ne peut être initialisée qu’une seule fois, via un initialiseur ou une instruction d’affectation. Il n’est pas nécessaire de l’initialiser au moment de la déclaration: il s’agit d’une variable “vierge finale”. Une variable d’instance finale vierge d’une classe doit être définitivement affectée à la fin de chaque constructeur de la classe dans laquelle elle est déclarée; de même, une variable statique finale vierge doit être définitivement affectée dans un initialiseur statique de la classe dans laquelle elle est déclarée: sinon, une erreur de compilation survient dans les deux cas. (Remarque: si la variable est une référence, cela signifie que la variable ne peut pas être liée à un autre object. Mais l’object auquel elle fait référence est toujours modifiable, s’il était modifiable à l’origine.)

Le final mot clé appliqué à un champ a l’un des deux effets suivants:

  • sur une primitive, cela empêche la modification de la valeur de la primitive (un int ne peut pas changer la valeur)
  • sur un object, cela empêche la “valeur de la variable”, c’est-à-dire la référence à l’object, d’être modifiée. Autrement dit, si vous avez un final HashMap a , vous ne pourrez le définir qu’une seule fois et vous ne pourrez pas le this.a=new HashMap(); encore une fois, mais rien ne vous empêche de faire this.a.put("a","b") , s puisque cela ne modifie pas la référence, seulement le contenu de l’object.

Le final modificateur vous empêche de modifier la valeur des variables, vous devez donc l’initialiser à l’endroit où vous le déclarez.

La spécification de langue contient des garanties spécifiques sur les propriétés des variables et des champs finaux. L’une d’elles est qu’un object correctement construit (c’est-à-dire dont le constructeur a abouti) doit avoir tous ses champs d’instance finaux initialisés et visibles pour tous les threads. Ainsi, le compilateur parsing les chemins de code et vous oblige à initialiser ces champs.

Final modifier ne permet pas de change your variable value . Vous devez donc lui atsortingbuer une valeur à un endroit donné et le constructor est l’endroit où vous devez le faire dans ce cas.