web-dev-qa-db-fra.com

Constantes et variables de compilation

La documentation du langage Java indique:

Si un type primitif ou une chaîne est défini comme une constante et que la valeur est connue au moment de la compilation, le compilateur remplace le nom de la constante partout dans le code par sa valeur. C'est ce qu'on appelle une constante de compilation.

Ma compréhension est que si nous avons un morceau de code:

private final int x = 10;

Ensuite, le compilateur remplacera chaque occurrence de x dans le code par littéral 10.


Mais supposons que la constante soit initialisée au moment de l'exécution:

private final int x = getX(); // here getX() returns an integer value at run-time.

Y aura-t-il une baisse des performances (aussi négligeable soit-elle) par rapport à la constante de temps de compilation?


Une autre question est de savoir si la ligne de code ci-dessous:

private int y = 10; // here y is not final

est traité de la même manière que la constante de compilation par le compilateur?


Enfin, ce que je comprends des réponses sont:

  1. final static signifie constante de compilation
  2. juste final signifie que c'est une constante mais est initialisée au moment de l'exécution
  3. juste static signifie initialisé au moment de l'exécution
  4. sans final est une variable et ne serait pas traitée comme constante.

Ma compréhension est-elle correcte?

38
NINCOMPOOP

La constante de temps de compilation doit être:

  • déclaré final
  • primitive ou String
  • initialisé dans la déclaration
  • initialisé avec une expression constante

Donc private final int x = getX(); n'est pas constant.

À la deuxième question private int y = 10; n'est pas constant (non final dans ce cas), donc l'optimiseur ne peut pas être sûr que la valeur ne changera pas à l'avenir. Il ne peut donc pas l'optimiser aussi bien qu'une valeur constante. La réponse est: non, elle n'est pas traitée de la même manière que la constante de temps de compilation.

56
msi

JLS fait les distinctions suivantes entre les variables et les constantes final:

final variables

Une variable peut être déclarée final. Une variable final ne peut être affectée qu'à une seule fois. Il s'agit d'une erreur de compilation si une variable final est affectée à moins qu'elle ne soit définitivement non affectée immédiatement avant l'affectation ( §16 (Assignation définie) ).

Une fois qu'une variable final a été affectée, elle contient toujours la même valeur. Si une variable final contient une référence à un objet, l'état de l'objet peut être modifié par des opérations sur l'objet, mais la variable fera toujours référence au même objet. Cela s'applique également aux tableaux, car les tableaux sont des objets; si une variable final contient une référence à un tableau, les composants du tableau peuvent être modifiés par des opérations sur le tableau, mais la variable fera toujours référence au même tableau.

Une vide final est une variable final dont la déclaration n'a pas d'initialiseur.

constantes

Une variable constante est une variable final de type primitif ou de type String qui est initialisée avec une expression constante (- §15.28 ).

A partir de cette définition, nous pouvons discerner qu'une constante doit être:

  • déclaré final
  • de type primitif ou de type String
  • initialisé dans sa déclaration (pas un vide final)
  • initialisé avec un expression constante

Qu'en est-il des constantes au moment de la compilation?

JLS ne contient pas la constante de temps de compilation de l'expression . Cependant, les programmeurs utilisent souvent les termes constante de compilation et constante de manière interchangeable .

Si une variable final ne remplit pas les critères énoncés ci-dessus pour être considérée comme une constante, elle doit techniquement être appelée variable final.

4
user9514304

Selon JLS, il n'est pas nécessaire que la "variable constante" soit statique.

Donc, "variable constante" peut être statique ou non statique (variable d'instance).

Mais JLS impose d'autres exigences pour qu'une variable soit une "variable constante" (en plus d'être juste finale):

  • étant uniquement String ou primitif
  • initialisé en ligne uniquement, car il est final, et la finale vide n'est pas autorisée
  • initialisé avec "expression constante" = "expression constante au moment de la compilation" (voir la citation JLS ci-dessous)

4.12.4. Variables finales (JLS)

Une variable constante est une variable finale de type primitif ou de type String qui est initialisée avec une expression constante (§15.28 ) .

15.28. Expressions constantes

Une expression de constante de compilation est une expression désignant une valeur de type primitif ou une chaîne qui ne se termine pas brusquement et se compose uniquement des éléments suivants:

Littéraux de type primitif et littéraux de type String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)

Conversion en types primitifs et conversion en type String (§15.16)

Les opérateurs unaires +, -, ~ et! (mais pas ++ ou -) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)

Les opérateurs multiplicatifs *,/et% (§15.17)

Les opérateurs additifs + et - (§15.18)

Les opérateurs de décalage <<, >> et >>> (§15.19)

Les opérateurs relationnels <, <=,> et> = (mais pas instanceof) (§15.20)

Les opérateurs d'égalité == et! = (§15.21)

Les opérateurs binaires et logiques &, ^ et | (§15.22)

L'opérateur conditionnel et && et l'opérateur conditionnel ou || (§15.23, §15.24)

L'opérateur conditionnel ternaire? : (§15.25)

Expressions entre parenthèses (§15.8.5) dont l'expression contenue est une expression constante.

Noms simples (§6.5.6.1) qui font référence à des variables constantes (§4.12.4).

Noms qualifiés (§6.5.6.2) du formulaire TypeName. Identifiant faisant référence à des variables constantes (§4.12.4).

2
Code Complete

Le mot clé final signifie qu'une variable sera initialisée une seule fois. Une réelle constante doit également être déclarée static. Ainsi, aucun de vos exemples n'est traité comme des constantes par le compilateur. Néanmoins, le mot clé final vous indique (et au compilateur) que vos variables seront initialisées une seule fois (dans le constructeur ou littéralement). Si vous avez besoin que leurs valeurs soient attribuées au moment de la compilation, vos champs doivent être statiques.

Les performances ne sont pas vraiment affectées, mais gardez à l'esprit que les types primitifs sont immuables, une fois que vous en avez créé un, il conservera cette valeur en mémoire jusqu'à ce que le garbage collector la supprime. Donc, si vous avez une variable y = 1; puis vous le changez en y = 2; en mémoire, la JVM aura les deux valeurs, mais votre variable "pointera" sur cette dernière.

privé int y = 10; // ici y n'est pas définitif

est traité de la même manière que la constante de temps de compilation par le compilateur?

Non. Il s'agit d'une variable d'instance, créée, initialisée et utilisée lors de l'exécution.

1
megathor

Il y a peut-être une vraiment petite baisse de performance sur certaines machines pour private final int x = getX(); car cela impliquerait au moins un appel de méthode ( outre le fait que ce n'est pas une constante de temps de compilation) mais comme vous l'avez dit, ce serait négligeable alors pourquoi s'embêter?

Quant à la deuxième question: y n'est pas finale et n'est donc pas une constante de temps de compilation, car elle peut changer au moment de l'exécution.

1
Thomas

private final int x = getX(); Sera appelé la première fois que votre objet sera déclaré. La performance "drop" dépendra de getX() mais ce n'est pas le genre de choses pour créer un goulot d'étranglement.

0
UmNyobe

En termes simples, lors de la compilation, le compilateur remplace la référence par la valeur réelle spécifiée, au lieu d'utiliser le paramètre de référence.

public static void main(String[] args) {
final int x = 5;
}

c'est à dire. lors de la compilation, le compliant prend directement la valeur initialisée de 5 pour la comparaison plutôt que d'utiliser la variable de référence "x";

Veuillez vérifier cette explication

0
Nick