java - tag - Constantes y variables en tiempo de compilación
para que sirve const int en c++ (7)
Cada literal Literal y String Literal es una constante de compilación.
Consulte: §15.28
La documentación del lenguaje Java dice:
Si un tipo primitivo o una cadena se define como una constante y el valor se conoce en tiempo de compilación, el compilador reemplaza el nombre de la constante en todas partes del código con su valor. Esto se llama una constante de tiempo de compilación.
Mi entendimiento es si tenemos un trozo de código:
private final int x = 10;
Luego, el compilador 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 compilació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 el compilador?
Finalmente, lo que entiendo de las respuestas son:
-
final static
significa constante de compilación - solo
final
significa que es una constante pero se inicializa en tiempo de ejecución - solo
static
significa inicializado en tiempo de ejecución - sin
final
es una variable y no sería tratado como constante.
¿Mi entendimiento es correcto?
El docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4 hace las siguientes distinciones entre variables final
y constantes:
variables final
Una variable puede ser declarada
final
. Una variablefinal
solo puede ser asignada a una vez. Es un error de tiempo de compilación si se asigna una variablefinal
a menos que esté definitivamente sin asignar 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 variablefinal
contiene una referencia a un objeto, entonces el estado del objeto puede cambiarse 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 variablefinal
contiene una referencia a una matriz, entonces los componentes de la matriz pueden cambiarse mediante operaciones en la matriz, pero la variable siempre se referirá a la misma matriz.Una
final
blanco es una variablefinal
cuya declaración carece de un inicializador.
constantes
Una variable constante es una variable
final
de tipo primitivo o tipoString
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 declaración (no es un
final
blanco ) - Inicializado con una §15.28
¿Qué pasa con las constantes de tiempo de compilación?
El docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4 no contiene la frase constante de tiempo de compilación . Sin embargo, los programadores a menudo usan los términos tiempo de compilación constante y constante de manera intercambiable.
Si una variable final
no cumple con los criterios descritos anteriormente para que se considere una constante, técnicamente debe denominarse una variable final
.
La constante de tiempo de compilación debe ser:
- declarado final
- primitivo o cadena
- inicializado dentro de la declaración
- 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 final en este caso), por lo que el optimizador no puede estar seguro de que el valor no cambiará 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 compilación.
La palabra clave final
significa que una variable se inicializará una vez y solo una vez. Una constante constante también debe ser declarada static
. Entonces, ninguno de sus ejemplos son tratados como constantes por el compilador. Sin embargo, la palabra clave final le dice (y al compilador) que sus variables se inicializarán solo una vez (en el constructor o literalmente). Si necesita sus valores asignados en tiempo de compilación, sus campos deben ser estáticos.
El rendimiento no es realmente el 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 y = 10; // aquí y no es final
¿Se trata de la misma manera que el compilador?
No. Esta es una variable de instancia, creada, inicializada y utilizada en tiempo de ejecución.
Según JLS, no hay ningún requisito de que "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 simplemente final):
- siendo solo cuerdas o primitivos
- inicializado solo en línea, porque es final y no se permite final en blanco
- inicializado con "expresión constante" = "expresión constante de tiempo de compilación" (vea la cita JLS a continuación)
docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4 docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4
Una variable constante es una variable final de tipo primitivo o tipo String que se inicializa con una expresión constante (§15.28) .
Una expresión constante de tiempo de compilación es una expresión que denota un valor de tipo primitivo o una cadena que no se completa de forma abrupta y se compone utilizando solo lo siguiente:
Literales de tipo primitivo y literales de tipo String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)
Conversión a tipos primitivos y conversión a tipo 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 condicional y el 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 hace referencia a variables constantes (§4.12.4).
private final int x = getX();
Se llamará la primera vez que se declare su objeto. El "descenso" del rendimiento dependerá de getX()
pero ese no es el tipo de cosas para crear un cuello de botella.
Puede haber una caída muy pequeña en el rendimiento en algunas máquinas para private final int x = getX();
ya que eso implicaría al menos una llamada al método (además del hecho de que esto no es una constante de compilación), pero como dijiste, sería insignificante, así que, ¿para qué molestarse?
En cuanto a la segunda pregunta: y
no es final y, por lo tanto, no es una constante de tiempo de compilación, ya que podría cambiar en tiempo de ejecución.