sirve - ¿Por qué Java requiere una conversión explícita en una variable final si se copió de una matriz?
static programacion (3)
De hecho, es lo que el compilador hace en plegado constante cuando se usa con
final
, como podemos ver en el código de bytes:
byte f = 1;
// because compiler still use variable ''f'', so `f + f` will
// be promoted to int, so we need cast
byte ff = (byte) (f + f);
final byte s = 3;
// here compiler will directly compute the result and it know
// 3 + 3 = 6 is a byte, so no need cast
byte ss = s + s;
//----------------------
L0
LINENUMBER 12 L0
ICONST_1 // set variable to 1
ISTORE 1 // store variable ''f''
L1
LINENUMBER 13 L1
ILOAD 1 // use variable ''f''
ILOAD 1
IADD
I2B
ISTORE 2 // store ''ff''
L2
LINENUMBER 14 L2
ICONST_3 // set variable to 3
ISTORE 3 // store ''s''
L3
LINENUMBER 15 L3
BIPUSH 6 // compiler just compute the result ''6'' and set directly
ISTORE 4 // store ''ss''
Y si cambia su byte final a 127, también se quejará:
final byte s = 127;
byte ss = s + s;
en cuyo caso, el compilador calcula el resultado y lo conoce fuera de límite, por lo que aún se quejará de que son incompatibles.
Más:
Y here hay otra pregunta sobre el plegado constante con una cuerda:
Comenzando con el siguiente código ...
byte foo = 1;
byte fooFoo = foo + foo;
Cuando intente compilar este código, obtendré el siguiente error ...
Error: (5, 27) Java: tipos incompatibles: posible conversión con pérdida de int a byte
... pero si
foo
es final ...
final byte foo = 1;
final byte fooFoo = foo + foo;
El archivo se compilará correctamente.
Pasando al siguiente código ...
final byte[] fooArray = new byte[1];
fooArray[0] = 1;
final byte foo = fooArray[0];
fooArray[0] = 127;
System.out.println("foo is: " + foo);
... imprimirá
foo is: 1
... lo cual está bien.
El valor se copia a una variable final y ya no se puede cambiar.
Jugar con el valor en la matriz no cambia el valor del
foo
(como se esperaba ...).
¿Por qué lo siguiente requiere un yeso?
final byte[] fooArray = new byte[1];
fooArray[0] = 1;
final byte foo = fooArray[0];
final byte fooFoo = foo + foo;
¿Cómo es esto diferente al segundo ejemplo en esta pregunta? ¿Por qué el compilador me da el siguiente error?
Error: (5, 27) Java: tipos incompatibles: posible conversión con pérdida de int a byte
¿Cómo puede pasar esto?
El JLS ( §5.2 ) tiene reglas especiales para la conversión de asignaciones con expresiones constantes :
Además, si la expresión es una expresión constante ( §15.28 ) de tipo
byte
,short
,char
oint
:
- Se puede usar una conversión primitiva estrecha si el tipo de la variable es
byte
,short
ochar
, y el valor de la expresión constante es representable en el tipo de la variable.
Si seguimos el enlace anterior, los vemos en la definición de expresión constante :
Si seguimos el segundo enlace de arriba, vemos que
Una variable de tipo primitivo o tipo
String
, que esfinal
e inicializada con una expresión constante en tiempo de compilación ( §15.28 ), se llama variable constante .
Se deduce que
foo + foo
solo se puede asignar a
fooFoo
si
foo
es una
variable constante
.
Para aplicar eso a sus casos:
-
byte foo = 1;
no define una variable constante porque no esfinal
. -
final byte foo = 1;
define una variable constante , porque esfinal
e inicializada con una expresión constante (un literal primitivo). -
final byte foo = fooArray[0];
no define una variable constante porque no se inicializa con una expresión constante .
Tenga en cuenta que si
fooFoo
es en sí mismo
final
no importa.
El valor 1 encaja perfectamente en un byte;
también lo hace 1 + 1;
y cuando la variable es final, el compilador puede hacer
un plegado constante
.
(en otras palabras: el compilador no usa
foo
cuando hace esa operación +, pero los valores "en bruto" 1)
Pero cuando la variable no es final, entran en juego todas las reglas interesantes sobre conversiones y promociones (vea here ; desea leer la sección 5.12 sobre cómo ampliar las conversiones primitivas).
Para la segunda parte: hacer una matriz final aún le permite cambiar cualquiera de sus campos; así que de nuevo; no es posible doblar constantemente; para que la operación de "ensanchamiento" vuelva a funcionar.