La variación de la conducta para una posible pérdida de precisión
-
01-10-2019 - |
Pregunta
En Java, cuando lo hace
int b = 0;
b = b + 1.0;
Se obtiene una posible pérdida de precisión de error. Pero por qué es que si lo hace
int b = 0;
b += 1.0;
No hay ningún error?
Solución
Esto se debe a b += 1.0;
es equivalente a b = (int) ((b) + (1.0));
. Los estrechamiento de conversión primitiva (JLS 5.1.3) se oculta en la operación de asignación compuesto.
JLS 15.26. 2 operadores de asignación compuestos (JLS Tercera Edición):
A expresión de asignación compuesto de la forma E1 op = E2 es equivalente a E1 = (T) ((E1) op (E2)) , donde T es el tipo de E1 , excepto que E1 se evalúa sólo una vez.
Por ejemplo, el siguiente código es correcto:
short x = 3; x += 4.6;
y resultados en
x
que tiene la7
valor porque es equivalente a:short x = 3; x = (short)(x + 4.6);
Esto también explica por qué las compilaciones de código siguiente:
byte b = 1;
int x = 5;
b += x; // compiles fine!
Pero esto no:
byte b = 1;
int x = 5;
b = b + x; // DOESN'T COMPILE!
Es necesario convertir explícitamente en este caso:
byte b = 1;
int x = 5;
b = (byte) (b + x); // now it compiles fine!
Vale la pena señalar que el reparto implícito en las asignaciones de compuestos es el tema de Puzzle 9: Tweedledum del libro maravilloso Puzzlers Java . Éstos son algunos extracto del libro (editado ligeramente por razones de brevedad):
Muchos programadores piensan que
.x += i;
es simplemente una abreviatura dex = x + i;
. Esto no es del todo cierto: si el tipo del resultado es más amplio que el de la variable, las preformas operador de asignación compuesto un estrechamiento conversión primitiva silenciosoPara evitar sorpresas desagradables, no utilice operadores de asignación compuestos en variables de tipo
byte
,short
, ochar
. Al utilizar operadores de asignación compuestos en variables de tipoint
, asegurarse de que la expresión en el lado derecho no es de tipolong
,float
, odouble
. Al utilizar operadores de asignación compuestos en variables de tipofloat
, asegurarse de que la expresión en el lado derecho no es de tipodouble
. Estas reglas son suficientes para evitar que el compilador de generar moldes de estrechamiento peligrosas.Para los diseñadores del lenguaje, es probablemente un error para los operadores de asignación compuestos para generar moldes invisibles; asignaciones compuestos donde la variable tiene un tipo más estrecho que el resultado del cálculo probablemente debería ser ilegal.
El último párrafo es digno de mención: C # es mucho más estricta en este sentido (véase C # Language Specification 7.13.2 asignación Compuesto ).