Constantes y variables de tiempo de comstackción

La documentación del lenguaje Java dice:

Si un tipo primitivo o una cadena se definen como una constante y el valor se conoce en tiempo de comstackción, el comstackdor reemplaza el nombre de la constante en todas partes del código con su valor. Esto se llama una constante de tiempo de comstackción.

Entiendo que tenemos un código:

private final int x = 10; 

Entonces, el comstackdor reemplazará cada aparición de x en el código con el literal 10 .


Pero supongamos que la constante se inicializa en tiempo de ejecución:

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

¿Habrá alguna caída en el rendimiento (por insignificante que sea) en comparación con la constante de tiempo de comstackción?


Otra pregunta es si la siguiente línea de código:

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

se trata de la misma manera que la constante de comstackción en tiempo por el comstackdor?


Finalmente, lo que entiendo de las respuestas es:

  1. final static significa constante de tiempo de comstackción
  2. simplemente final significa que es una constante, pero se inicializa en tiempo de ejecución
  3. solo static significa inicializado en tiempo de ejecución
  4. sin final es una variable y no se tratará como constante.

Es mi entendimiento correcto?

La constante de tiempo de comstackción debe ser:

  • declarado final
  • primitivo o cadena
  • inicializado dentro de la statement
  • Inicializado con expresión constante

Entonces private final int x = getX(); no es constante.

A la segunda pregunta private int y = 10; no es constante (no es final en este caso), por lo que el optimizador no puede estar seguro de que el valor no cambie en el futuro. Por lo tanto, no puede optimizarlo tan bien como el valor constante. La respuesta es: No, no se trata de la misma manera que la constante de tiempo de comstackción.

La palabra clave final significa que una variable se inicializará una vez y solo una vez. Una necesidad real constante de ser declarado static también. Entonces, ninguno de sus ejemplos es tratado como constantes por el comstackdor. Sin embargo, la palabra clave final le dice (y al comstackdor) que sus variables se inicializarán una sola vez (en el constructor o literalmente). Si necesita sus valores asignados en tiempo de comstackción, sus campos deben ser estáticos.

El rendimiento en realidad no se ve tan afectado, pero tenga en cuenta que los tipos primitivos son inmutables; una vez que haya creado uno, mantendrá ese valor en la memoria hasta que el recolector de basura lo elimine. Entonces, si tienes una variable y = 1; y luego lo cambias a y = 2; en la memoria, la JVM tendrá ambos valores, pero su variable “apuntará” a la última.

int privado = 10; // aquí y no es final

se trata de la misma manera que la comstackción de tiempo constante por el comstackdor?

No. Esta es una variable de instancia, creada, inicializada y utilizada en tiempo de ejecución.

Puede haber una caída de rendimiento muy pequeña en algunas máquinas para private final int x = getX(); ya que implicaría al menos una llamada al método (además del hecho de que no es una constante en tiempo de comstackción), pero como dijiste, sería insignificante, ¿por qué molestarse?

En cuanto a la segunda pregunta: y no es final y por lo tanto no es una constante de tiempo de comstackción, ya que podría cambiar en tiempo de ejecución.

private final int x = getX(); Se llamará la primera vez que se declara tu objeto. La “caída” de rendimiento dependerá de getX() pero ese no es el tipo de cosas para crear un cuello de botella.

Según JLS, no hay ningún requisito de que la “variable constante” sea estática.

Entonces, “variable constante” puede ser estática o no estática (variable de instancia).

Pero JLS impone algunos otros requisitos para que una variable sea una “variable constante” (además de ser solo final):

  • siendo solo Cadena o primitivo
  • inicializado solo en línea, porque es final y no se permite una final en blanco
  • inicializado con “expresión constante” = “expresión constante en tiempo de comstackción” (ver la cita de JLS a continuación)

4.12.4. Variables finales (JLS)

Una variable constante es una variable final de tipo primitivo o tipo String que se inicializa con una expresión constante (§15.28) .

15.28. Expresiones constantes

Una expresión constante de tiempo de comstackción es una expresión que denota un valor de tipo primitivo o una cadena que no se completa abruptamente y se compone solo con lo siguiente:

Literales de tipo primitivo y literales de tipo Cadena (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)

Transmite a los tipos y moldes primitivos para escribir String (§15.16)

Los operadores unarios +, -, ~ y! (pero no ++ o -) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)

Los operadores multiplicativos *, / y% (§15.17)

Los operadores aditivos + y – (§15.18)

Los operadores de cambio < <, >> y >>> (§15.19)

Los operadores relacionales < , <=,> y> = (pero no instanceof) (§15.20)

Los operadores de igualdad == y! = (§15.21)

Los operadores bit a bit y lógicos &, ^, y | (§15.22)

El operador condicional y operador && y el condicional u operador || (§15.23, §15.24)

¿El operador condicional ternario? : (§15.25)

Expresiones entre paréntesis (§15.8.5) cuya expresión contenida es una expresión constante.

Nombres simples (§6.5.6.1) que se refieren a variables constantes (§4.12.4).

Nombres calificados (§6.5.6.2) de la forma TypeName. Identificador que se refiere a variables constantes (§4.12.4).

El JLS hace las siguientes distinciones entre las variables final y las constantes:

variables final

Una variable puede declararse final . Una variable final solo se puede asignar a una vez. Es un error en tiempo de comstackción si se asigna una variable final a menos que definitivamente no se asigne inmediatamente antes de la asignación ( §16 (Asignación Definitiva) ).

Una vez que se ha asignado una variable final , siempre contiene el mismo valor. Si una variable final contiene una referencia a un objeto, entonces el estado del objeto puede modificarse mediante operaciones en el objeto, pero la variable siempre se referirá al mismo objeto. Esto se aplica también a las matrices, porque las matrices son objetos; si una variable final contiene una referencia a una matriz, los componentes de la matriz pueden modificarse mediante operaciones en la matriz, pero la variable siempre se referirá a la misma matriz.

Una final blanco es una variable final cuya statement carece de un inicializador.

constantes

Una variable constante es una variable final de tipo primitivo o tipo String que se inicializa con una expresión constante ( §15.28 ).

A partir de esta definición, podemos discernir que una constante debe ser:

  • declarado final
  • de tipo primitivo o tipo String
  • Inicializado dentro de su statement (no es una final blanco )
  • Inicializado con una expresión constante

¿Qué pasa con las constantes de tiempo de comstackción?

El JLS no contiene la frase constante de tiempo de comstackción . Sin embargo, los progtwigdores a menudo usan los términos tiempo de comstackción constante y constante de manera intercambiable.

Si una variable final no cumple con los criterios descritos anteriormente para ser considerada una constante, técnicamente debe denominarse como una variable final .

Cada Literal y Literal primitivo es una constante en tiempo de comstackción.

Ver: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28